# Klaytn 문서

{% hint style="info" %}
본 문서는 Klatyn에 대한 보관된 문서이며 더 이상 업데이트되지 않고 있습니다. 최신 문서를 보려면 [새 문서 사이트](https://docs.klaytn.foundation/ko/)를 방문하세요.
{% endhint %}

Klaytn Docs introduces [Klaytn](http://klaytn.foundation), an enterprise-grade, service-centric platform that brings user-friendly blockchain experience to millions of users.

Read our [Lightpaper](https://klaytn.foundation/wp-content/uploads/Lightpaper.pdf).

<table data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Klaytn 개요</strong></td><td>Klaytn에 대해 알고 싶다면</td><td></td><td><a href="https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-6bf5e37d2b038d30f02574d95029803c905589af%2Fthum_01.png?alt=media">thum_01.png</a></td><td><a href="/content/klaytn">Klaytn Overview</a></td></tr><tr><td><strong>시작하기</strong></td><td>Klaytn에서 개발 시작하기</td><td></td><td><a href="https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-97b04940177cc2bfd9bafe54f4b979c0ae1b9878%2Fthum_02.png?alt=media">thum_02.png</a></td><td><a href="/content/installation-guide/deployment">배포</a></td></tr><tr><td><strong>노드 운영하기</strong></td><td>Klaytn 노드 운영하는 법 알아보기</td><td></td><td><a href="https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-4b6da81b5925f1913147debfa348f7c9c4e90306%2Fthum_03.png?alt=media">thum_03.png</a></td><td><a href="/content/installation-guide">Run a Node</a></td></tr><tr><td><strong>Awesome Klaytn</strong></td><td>Klaytn의 방대한 생태계에 관련된 모든 것!</td><td></td><td><a href="https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-ff9ccc774cb72108e7df79079494673cbd272b17%2Fthum_04.png?alt=media">thum_04.png</a></td><td><a href="https://github.com/klaytn/awesome-klaytn">https://github.com/klaytn/awesome-klaytn</a></td></tr><tr><td><strong>Klaytn 개발자 허브</strong></td><td>Klaytn 개발자 포털 사이트</td><td></td><td><a href="https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-867b613bc41c72f26b14ab02dbf08e097aaafd0c%2Fthum_05.png?alt=media">thum_05.png</a></td><td><a href="http://developer.klaytn.foundation">http://developer.klaytn.foundation</a></td></tr><tr><td><strong>Klaytn 개발자 포럼</strong></td><td>질문이 있나요? 포럼을 방문하세요!</td><td></td><td><a href="https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-dacecd845695d644e1cfbf0f335dc3313a4ee39a%2Fthum_06%20(1).png?alt=media">thum_06 (1).png</a></td><td><a href="http://forum.klaytn.foundation">http://forum.klaytn.foundation</a></td></tr></tbody></table>


# Klaytn Overview

클레이튼은 엔터프라이즈급 안정성을 목표로 고도로 최적화된, BFT 알고리즘 기반 퍼블릭 블록체인입니다. 주요 디자인 목표는 다음과 같습니다.

* 즉각적인 완결성
* 실제 사용 사례에서 문제 없는 높은 TPS
* Blockchain 애플리케이션 실행 비용 절감
* 사용자의 진입 장벽을 낮춤
* 산업계의 블록체인 기술 도입 촉진

클레이튼은 2019년 6월 27일에 다음과 같은 사양으로 메인넷 [Cypress](https://scope.klaytn.com/)을 출시했습니다.

* 1초의 블록 생성 및 확인(Confirm) 시간
* 초당 4,000 건의 트랜잭션
* 이더리움 1/10 수준의 낮은 가스비
* EVM(이더리움 가상머신)을 구동하여 솔리디티 컨트랙트 실행을 지원함
* 세계적으로 평판이 높은 19개 기업이 모여 최초의 클레이튼 거버넌스 카운슬을 결성하고 컨센서스 노드 운영을 시작함. 컨센서스에 참여하는 노드 개수 현황은 [Klaytnscope](https://scope.klaytn.com/)에서 볼 수 있습니다.
* 50개 이상의 초기 서비스 파트너가 클레이튼에서 블록체인 애플리케이션을 출시하려고 준비

## 클레이튼: 개관 <a href="#klaytn-the-big-picture" id="klaytn-the-big-picture"></a>

Klaytn은 역할 및 목적에 따라 세 개의 논리적 서브네트워크로 분할할 수 있습니다. 아래 그림은 Klaytn 생태계의 대략적인 구조를 보여줍니다.

![클레이튼 생태계 및 논리적 서브 네트워크 (CCN, ENN, SCN)](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-4dcf2b85f641b8cfab8ca14c38895be93c7dfaf0%2Fklaytn_network_overview.png?alt=media)

### 코어 셀 네트워크(CCN) <a href="#core-cell-network-ccn" id="core-cell-network-ccn"></a>

CCN은 엔드포인트 노드(EN)를 통해 제출된 트랜잭션을 확인하고 실행하는 코어 셀(CC, Core Cell)로 구성됩니다. CCN은 네트워크 전체에서 블록을 생성하고 전파합니다.

### 엔드포인트 노드 네트워크(ENN) <a href="#endpoint-node-network-enn" id="endpoint-node-network-enn"></a>

ENN은 주로 트랜잭션을 생성하고, RPC API 요청을 처리하며, 서비스체인의 데이터 요청을 처리하는 엔드포인트 노드(EN)로 구성됩니다.

### 서비스체인 네트워크(SCN) <a href="#service-chain-network-scn" id="service-chain-network-scn"></a>

SCN은 탈중앙화 애플리케이션(dApp)에 의해 독립적으로 운영되는 보조 블록체인들로 구성된 클레이튼 서브네트워크입니다. 서비스 체인은 EN을 통해 메인 체인에 연결됩니다.

**코어 셀 네트워크**와 **엔드포인트 노드 네트워크**은 클레이튼 메인체인과 메인넷을 구성합니다. 블록체인 애플리케이션은 클레이튼 메인 체인인 Cypress에서 실행하거나 자체적인 블록체인인 **서비스체인**에서 작동할 수 있습니다. 높은 TPS와 설정 변경이 가능한 네트워크 정책을 가진 전용 실행 환경을 원한다면 서비스체인을 사용하는 것을 추천합니다.

> 애플리케이션을 위한 서비스 체인을 설정하려면 [서비스 체인의 설치 및 운영 가이드](/content/installation-guide/deployment/service-chain/getting-started)를 읽어보세요.

## 클레이튼 네트워크 토폴로지 <a href="#klaytn-network-topology" id="klaytn-network-topology"></a>

이 장에서는 클레이튼 메인체인의 네트워크 토폴로지에 대해 설명합니다. 네트워크 성능을 최적화하기 위해 역할 기반 노드 유형에 따라 계층화된 네트워크 아키텍처가 구현되었습니다.

### 역할 기반 노드 유형 <a href="#role-based-node-types" id="role-based-node-types"></a>

클레이튼 메인체인 네트워크 토폴로지를 살펴보기 전에 다양한 유형의 클레이튼 노드를 알아보겠습니다.

#### 코어 셀(CC): 컨센서스 노드(CN) + 프록시 노드(PN) <a href="#core-cell-cc-consensus-node-cn-proxy-node-pn" id="core-cell-cc-consensus-node-cn-proxy-node-pn"></a>

코어 셀 (CC) 은 하나의 **컨센서스 노드 (CN)와 두 개의 프록시 노드 (PNs)로 구성됩니다. 합의 노드는 블록 생성 프로세서에 참여하고, 프록시 노드는 네트워크에 인터페이스를 제공합니다. PN은 트랜잭션 요청을 합의 노드로 전송하고 블록을 엔드포인트 노드로 전파합니다.**

**Core Cell Operator가 되기에 관심이 있다면,** [**Core Cell의 설치 및 운영 가이드를 읽어보세요**](/content/installation-guide/deployment/core-cell/installation-guide/before-you-install)**.엔드포인트 노드 (EN)Klaytn 네트워크의 엔드포인트로서, RPC API 요청을 처리하고 서비스 체인과의 데이터 전송을 담당합니다.애플리케이션을 위한 엔드포인트 노드를 설정하려면,** [**엔드포인트 노드의 설치 및 운영 가이드**](/content/installation-guide/deployment/endpoint-node)**를 읽어보세요.부트노드부트노드는 Klaytn이 새로운 노드가 네트워크에 등록하고 다른 노드와 연결할 수 있도록 도와주는 특별한 유형의 노드입니다. CN 부트노드는 CNN 내부에 위치해 있고 공개되지 않은 반면, PN과 EN 부트노드는 공개적으로 볼 수 있습니다. PN 부트노드는 허가된 PN만 등록할 수 있게 하고, 적합한 PN들이 EN과 연결될 수 있도록 합니다. EN 부트노드는 EN들에게 어떤 PN에 연결해야 하는지에 대한 정보를 제공합니다. <0>계층화된 네트워크CN, PN, 그리고 EN은 각각 논리적 네트워크를 형성하며, 이는 컨센서스 노드 네트워크 (CNN), 프록시 노드 네트워크 (PNN), 그리고 엔드포인트 노드 네트워크 (ENN) 입니다.아래의 그림은 Klaytn 메인넷의 전체 토폴로지를 보여주며, 여기에서 코어 셀 네트워크 (CCN) 은 컨센서스 노드 네트워크 (CNN) 과 프록시 노드 네트워크 (PNN) 으로 더 세분화됩니다. 엔드포인트 노드 네트워크 (ENN) 는 PNN에 직접 연결된 주변 네트워크로도 표시됩니다.컨센서스 노드 네트워크CN들은 CNN이라고 불리는 자체적으로 완전 연결망(full-mesh network) 을 형성합니다. CNN은 WAN(wide area network) 상에서 BFT를 적용하고, 각 CN이 충분한 성능 수준에서 BFT 합의를 수행하기 위해** [**엄격한 하드웨어와 네트워크 리소스 요구 사항**](/content/installation-guide/deployment/core-cell/system-requirements)**을 충족해야 합니다.프록시 노드 네트워크 (PNN)PNN은 PN(프록시 노드) 들로 구성됩니다. 일반적으로, PN들은 이웃하는 코어 셀에 있는 하나의 PN과만 연결을 유지합니다. 피어 연결의 수는 네트워크 구성에 따라 변경될 수 있습니다.엔드포인트 노드 네트워크 (ENN)가장 바깥쪽의 하위 네트워크인 ENN은 서로 연결된 EN(엔드포인트 노드) 들만으로 구성되며, 일부 PN에도 연결됩니다.블록 생성 및 전파블록 생성과 전파 설계는 사용되는 합의 알고리즘과 함께 블록체인 플랫폼의 지연 시간을 줄이는 데 중요한 역할을 합니다.블록 생성 주기클레이튼에서의 '라운드'는 블록 생성 주기입니다.\</3> 각 라운드마다 새로운 블록을 생성하며, 바로 다음에 새로운 라운드가 시작됩니다. Klaytn은 각 라운드가 대략 1초가 되도록 목표를 설정하고 있지만, 블록 생성 간격은 네트워크 트래픽과 노드 운영 상태에 영향을 받을 수 있습니다.제안자와 위원회 선택각 라운드에서 Klaytn은 무작위로 하지만 결정론적으로 블록을 생성할 제안자로 컨센서스 노드 (CN) 를 선택하고, 그 라운드에 대한 위원회로 CN 그룹을 선택합니다. Klaytn은 제안자나 위원회의 선택에 직접 관여하지 않습니다. 대신 각 CN은 가장 최근의 블록 헤더에서 파생된 난수를 사용하여 이 라운드에 대해 선택되었는지(또는 선택되지 않았는지) 증명하는 암호화 작업을 수행합니다. 위원회의 크기는 비잔틴 공격에 대한 저항력이 있어야 합니다. 만약 CNN의 크기가 작다면, 모든 CN(제안자 제외)은 위원회 멤버로 선택될 자격이 있습니다.블록 제안 및 검증선택되면 제안자는 모든 CN에게 그 라운드의 선택 증명(즉, 제안자의 공개 키로 검증 가능한 암호화 증명)을 전송합니다. 그 후에는, 해당 라운드의 위원회로 선택된 CN들이 제안자에게 자신의 선택 증명을 응답하여 새로 제안될 블록을 누구에게 전송할지 알립니다. 제안자는 그 후에 자신의 트랜잭션 풀에서 트랜잭션들을 선택하고 이를 정렬하여 블록을 생성합니다. 마지막으로, 제안자는 위원회와 합의를 실행하여 새롭게 생성된 블록을 승인하고 확정합니다. Klaytn은 계속해서 더 높은 보안성과 효율성을 달성하기 위해 합의 알고리즘을 개선할 계획입니다.블록 전파제안된 블록은 위원회 구성원의 3분의 2 이상으로부터 서명을 받아야만 성공적으로 확정됩니다.\</3> 위원회가 합의에 도달하면, 새로운 블록은 모든 CN에게 전파되고 컨센서스 라운드가 종료됩니다. 새로운 블록이 모든 CN에게 전파되면, 새롭게 생성된 블록의 정보는 PNN을 통해 ENN에 블록 헤더와 바디 데이터를 전달함으로써 모든 Klaytn 네트워크 참가자에게 제공될 수 있습니다.공개 및 공개 검증Klaytn 네트워크의 서비스 제공자와 사용자는 블록 생성 결과를 자유롭게 검증하고 CN 위원회가 적절한 절차에 따라 블록을 생성했는지 확인할 수 있습니다. 이러한 검증에는 블록 헤더에 위원회 서명의 3분의 2 이상을 포함하는지 확인하는 작업이 포함됩니다. 모든 CN들은 공개 검증을 지원해야 하며, 그들의 공개 키(블록에 서명하는 데 사용됨)를 공개적으로 접근 가능한 공간(예: 블록 헤더)에 게시해야 합니다. 공개 검증은 투명성을 증진시키고 검열을 방지하며 악의적인 행동을 예방합니다.블록과 트랜잭션을 위한 분리된 전파 채널 (멀티채널 전파)네트워크의 지연 시간은 그 정체도에 크게 영향을 받습니다. 네트워크의 처리량이 일정하다고 가정할 때, 트랜잭션의 증가는 네트워크의 지연 시간이 비례적으로 지연됩니다. 지연 시간은 dApps에서 중요한 문제입니다. 레거시 모바일 앱이나 웹 서비스의 일반적인 사용자들은 몇 초 이상의 응답 시간을 참을 수 없으며, 블록체인 서비스도 더 높은 사용자 인내를 가정할 이유가 없습니다.Klaytn은 네트워크의 지연 문제를 처리하기 위해 멀티 접근 방식을 채택합니다. 트랜잭션과 블록에 대한 별도의 전파 채널을 할당함으로써, Klaytn 네트워크는 높은 트랜잭션 수로 인한 심각한 정체 상황에서도 새로 생성된 블록을 적시에 전파할 수 있습니다. 이렇게 함으로써 Klaytn은 그 네트워크의 dApps이 간헐적인 네트워크 트래픽 급증에도 불구하고 최종 사용자의 요청에 신속하게 응답할 수 있도록 보장합니다.블록 보상각 라운드마다 블록 보상(6.4개의 새로 생성된 KLAY와 블록을 처리하기 위해 지불된 트랜잭션 수수료의 합계) 이 미리 설정된 분배 비율에 따라 네트워크 참가자에게 분배됩니다. 새로 생성된 블록의 제안자는 CN에게 주어질 보상의 100%를 받을 것이며, 위원회는 보상을 받지 않을 것입니다. 제안자로 선택될 확률은 CN이 플랫폼에 스테이킹한 KLAY의 양에 영향을 받는다는 것에 유의해야 합니다. 즉, 더 많은 KLAY를 투자한 CN은 확률적으로 더 많은 보상을 받을 것입니다. 블록 보상 분배의 자세한 내용은** [**Klaytn Token Economy**](/content/klaytn/design/token-economy) **섹션에서 찾을 수 있습니다.**


# 왜 클레이튼일까요?

이 문서는 클레이튼의 핵심 설계 원칙을 기반으로 클레이튼의 차별점을 설명합니다.

## 클레이튼, 메타버스의 신뢰 레이어 <a href="#klaytn-as-a-trust-layer-of-metaverse" id="klaytn-as-a-trust-layer-of-metaverse"></a>

​오픈소스 퍼블릭 블록체인 프로젝트 클레이튼은 모든 커뮤니티의 참여와 기여를 존중하고, 이들을 지지하며, 새로운 세상에 결집시키는 메타버스를 위한 근본적 신뢰 레이어로서 구상되었습니다. 가장 중요한 디자인 원칙은 다음과 같습니다.

{% hint style="success" %}
선구자들이 확장 가능한 방식으로 어플리케이션을 만들고 커뮤니티를 조직할 수 있도록 도와줍니다.
{% endhint %}

​이 원칙에 따라 클레이튼은 다음 요구 사항들을 충족하도록 설계되었습니다​

### 우수한 성능 <a href="#high-performance" id="high-performance"></a>

#### 처리량(TPS)과 완결성 <a href="#throughput-and-finality" id="throughput-and-finality"></a>

* 메인체인은 최소 4,000 TPS 이상을 처리해야 합니다.
* 메인체인은 1초의 블록 생성 시간과 즉각적인 트랜잭션 완결성을 보장해야 합니다.
* See [Consensus Mechanism](/content/klaytn/design/consensus-mechanism). ​

#### 확장성 <a href="#scalability" id="scalability"></a>

* 서비스 체인은 맞춤형으로 쉽게 배포될 수 있는 Klaytn 2.0의 기본 L2 솔루션입니다. 서비스 체인은 자체 거버넌스를 보유할 수 있으며, 데이터 앵커링 및 자산 전송을 위해 클레이튼 메인체인에 연동될 수 있습니다.
* See [Service Chain](/content/klaytn/scaling-solutions#service-chain). 기업들이나 대규모 네트워크들은 자체적 실행 환경을 필요로 하는 경우가 많습니다. 서비스 체인을 이용하면 다른 블록체인 어플리케이션에 영향 받지 않는 분리된 고성능 실행 환경을 유지할 수 있습니다.
* 샤딩이나 롤업 등 기타 확장성 솔루션도 근시일 내에 출시될 예정입니다. ​

### 저렴한 비용 <a href="#low-cost" id="low-cost"></a>

* 사용자는 기존 시스템을 사용할 때에 비해 높은 트랜잭션 수수료를 부담해서는 안 됩니다.
* 트랜잭션 수수료는 안정적이어야 하고, 주변 요인이 아니라 트랜잭션의 복잡성 자체에 의해 결정되어야 합니다.
* See [Affordable Smart Contract Execution Cost](/content/klaytn/design/computation/klaytn-smart-contract#affordable-smart-contract-execution-cost) and [Transaction Fees](/content/klaytn/design/transaction-fees). For a gas price of 250 ston, a KLAY transfer would incur a fixed cost of 0.00525 KLAY. (21,000 Gas for KLAY transfer x (250 x 10^-9) == 0.00525 KLAY) ​

### 빠른 개발 <a href="#rapid-development" id="rapid-development"></a>

#### 이더리움 동일성 <a href="#ethereum-compatibility" id="ethereum-compatibility"></a>

* 개발 도구: 클레이튼 스택을 인터페에스와 실행 관점에서 기존의 이더리움 스택과 동일하게 보장함으로써 이더리움의 어떤 도구든 클레이튼 생태계에서 문제없이 동작할 수 있습니다. 클레이튼 생태계에서 만들어진 모든 도구는 이더리움 생태계에서도 상호적으로 도입될 수 있습니다.
* EVM과 API: 기존 이더리움 스택에 개발함으로써 EVM과 라이브러리의 오픈소스 코드 베이스에 추가된 모든 개선 사항들을 상속합니다. 클레이튼 EVM 환경과 동일한 옵코드와 스택 로직을 지원함으로써 실행 동작도 호환됩니다. 또한 동일한 엔드포인트 페이로드 구문을 지닌 JSON-RPC API를 지원하여 완전한 이더리움 인터페이스 호환성이 보장됩니다. See [Solidity-Smart Contract Language](/content/smart-contract/solidity-smart-contract-language), and [Migrating Ethereum App to Klaytn](/content/dapp/tutorials/migrating-ethereum-app-to-klaytn).
* Core Development Contribution: Supporting Ethereum equivalence translates most to the mutual benefit to both the Klaytn and Ethereum ecosystems. 대부분의 이더리움 개선 제안(EIP)은 클레이튼 코어 개발 어젠다에 이전, 적용될 수 있을 것이며 클레이튼 개선 제안(KIP) 또한 이더리움과 EVM의 발전에 기여할 수 있을 것입니다. 한 생태계에 대한 개발 커뮤니티의 기여는 두 생태계 모두에 대한 기여로 이어집니다. ​

#### 오픈소스 인프라 및 패키지 <a href="#open-source-infrastructure-and-package" id="open-source-infrastructure-and-package"></a>

* 일차적 인프라: 종단간(end-to-end) 블록체인 결합 및 개발을 위한 툴셋입니다. 여기에는 SDK와 스마트 컨트랙트 라이브러리, 월렛, 체인 탐색기, 분산 저장 솔루션, 오라클 지원, 브릿지가 포함됩니다.
* 이차적 인프라: 제품과 서비스 지원을 위한 생태계에 해당합니다. 여기에는 통합/추상화 서비스, 스테이블 코인 연동, DAO, NFT 마켓플레이스, DEX, DeFi, 전통 금융 인터페이스 등이 포함됩니다. ​

### 우수한 사용자 경험 <a href="#enhanced-user-experience" id="enhanced-user-experience"></a>

#### 트랜잭션의 사용성 <a href="#usability-in-transaction" id="usability-in-transaction"></a>

* 사용자의 트랜잭션 수수료를 서비스 운영자가 대신 지불할 수 있습니다.
* See [Fee Delegation](/content/klaytn/design/transactions#fee-delegation). 애플리케이션 운영자는 각 트랜잭션에 대한 보조금의 양을 설정할 수 있어서 프리미엄(freemium)이나 구독 모델 같이 더욱 유연한 비즈니스 모델을 사용할 수 있습니다. 수수료 위임 기능은 사용자 유입 장벽을 낮출 수 있습니다. ​ ​

### 프로토콜 수준의 전체 포괄 에코 펀드 <a href="#contribution-reward" id="contribution-reward"></a>

* 클레이튼은 생태계를 지원하는 인센티브들이 온체인 프로토콜 토크노믹스에 인코딩된 최초이자 최대 규모의 사례입니다. 신규 발행 토큰의 66%가 생태계에 재투자됩니다.
* See [Klaytn Improvement Reserve](/content/klaytn/design/token-economy#klaytn-improvement-reserve) and [Klaytn Growth Fund](/content/klaytn/design/token-economy#klaytn-growth-fund). ​ ​

### 커뮤니티 공동 구축 <a href="#community-co-building" id="community-co-building"></a>

* In addition to the protocol design, Klaytn will expand its territory through community co-building; it includes kinds of communities such as game guilds, investment DAOs, community DAOs, alliance with global players, etc. ​ Lastly, the ground rules: ​

{% hint style="success" %}
클레이튼은 위에서 언급한 개선 사항을 달성하되 블록체인의 핵심적인 특징을 희생하지 않으며, 적극적으로 헌신하는 참여자들과 함께 안정적으로 프로토콜 유지합니다.
{% endhint %}

### 투명성, 보안 및 탈중앙화 <a href="#transparency-security-and-decentralization" id="transparency-security-and-decentralization"></a>

* 누구나 블록체인에서 트랜잭션을 요청, 조회, 확인할 수 있습니다.
* 클레이튼은 탈중앙화된 네트워크이므로 하나의 악성 노드가 데이터 무결성을 손상시키지 않습니다. ​

### DAO, 빌더, 기업들의 거버넌스로 안정적인 탈중앙화 실현 <a href="#governance-by-trusted-entities" id="governance-by-trusted-entities"></a>

* 클레이튼 거버넌스 카운슬(GC)에 기존의 전통적 기업들에 더해 DAO 및 빌더들을 영입함으로써 클레이튼의 거버넌스 구조를 수백 개의 주체들이 참여하는 포함한 유례없는 방식으로 재정립할 가능성이 열립니다.


# 클레이튼 디자인


# 합의 메커니즘

합의 메커니즘(알고리즘)은 신뢰가 없는 주체들 간 합의에 도달하는 방법입니다. 블록체인 기술에서는 블록이 유효한지 아닌지에 대한 합의에 도달하는 데 사용됩니다. 블록체인 네트워크의 성능은 선택된 합의 메커니즘의 성능에 의존하며, 블록체인 애플리케이션의 사용성에 상당한 영향을 미칩니다.

Klaytn 메인넷 Cypress은 다음과 같은 성능을 보여줍니다.

* 초당 4,000 건의 트랜잭션을 처리합니다.
* 즉각적인 트랜잭션 완결성(finality)
* 1초의 블록 생성 시간
* 50개가 넘는 컨센서스 노드가 합의 프로세스에 참여할 수 있습니다.

이 문서에서 우리는 Klaytn이 어떻게 고성능 합의 프로세스를 구현했는지 살펴볼 것입니다.

## 배경 <a href="#background" id="background"></a>

[비트코인](https://en.wikipedia.org/wiki/Bitcoin)은 [PoW](https://en.wikipedia.org/wiki/Proof_of_work) (작업증명) 을 사용하고 있으며, 최근에 이더리움은 [PoS](https://en.wikipedia.org/wiki/Proof_of_stake) (지분증명) 로 전환되어 블록 생성 노드를 노드의 지분에 따라 결정합니다. 일반적으로 이러한 알고리즘은 블록의 유효성을 결정하는 과정에서 노드 간의 통신이 없습니다.

따라서 이러한 시스템에서는 포크가 발생할 수 있습니다. 즉, 같은 높이에서 둘 이상의 서로 다른 블록이 만들어질 수 있습니다. Usually, the "Longest chain wins" rule is applied to solve the fork condition. 포크가 일어난 체인이 결국 하나의 체인으로 병합되지만, 특정 기간 동안에 짧은 체인에 속한 블록들은 되돌려질 수 있다는 의미이기도 합니다. 그러므로 이러한 알고리즘에서는 블록 및 트랜잭션의 완결성을 즉시 보장 할 수 없습니다. 완결성은 일정 기간이 지난 후에만 확률적으로 달성될 수 있으며, 100% 보장되지 않을 수 있습니다.

This lack of finality is a very difficult issue in customer-facing services that use blockchain platforms. 포크가 해결되고, 블록이 충분히 쌓여서 트랜잭션을 되돌릴 수 없게 될 때까지 기다려야 하기 때문입니다. This has a negative effect both on users and service providers.

A simple example of this issue can be demonstrated in financial services. Say a user transferred money to someone, and the service can't verify that the transfer is valid until 30 to 60 minutes have passed. Because it has to wait until the forks have been merged into a single chain and several blocks are stacked after the transfer to be sure that the transaction is not reversible.

### PBFT (Practical Byzantine Fault Tolerance) <a href="#pbft-practical-byzantine-fault-tolerance" id="pbft-practical-byzantine-fault-tolerance"></a>

위의 문제를 방지하려면 완결성을 보장하는 다른 알고리즘이 필요합니다. BFT 알고리즘은 Lamport, Shostak, Pease에 의해 1982년에 처음 발표된 알고리즘입니다. 1999년, Miguel Castro와 Barbara Liskov는 high-performance state machine replication을 제공하는 "Practical Byzantine Fault Tolerance"(PBFT)를 도입했습니다.

위에서 설명한 PoW 알고리즘에서는 각 노드가 블록을 전송받고 검증하지만, 합의에 도달하기 위해 노드 간 메시지를 교환하지는 않습니다. 그러나 PBFT에서는 각 노드가 다른 참여 노드와 통신하여 합의에 도달하고 노드가 합의에 도달하는 즉시 블록의 완결성를 보장할 수 있습니다.

노드 간의 통신은 기본적으로 아래와 같이 진행됩니다. 하지만, 각 시스템에 따라 특성을 반영하는 몇 가지 예외가 있을 수 있습니다.

![PBFT message flow](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-19239f287eb2188135cf0574e3f00e839531c21d%2Fpbft.png?alt=media)

위와 같이 PBFT에 참여하는 노드는 기본적으로 네트워크의 모든 노드와 여러 단계에서 통신합니다. 이 특성은 노드 수가 증가할수록 통신량이 기하급수적으로 증가하므로 노드 수를 제한합니다.

## Klaytn의 합의 메커니즘 <a href="#consensus-mechanism-in-klaytn" id="consensus-mechanism-in-klaytn"></a>

Klaytn은 엔터프라이즈급 서비스 중심 플랫폼이 되는 것을 목표로 하고 있습니다. 따라서 위에서 설명한 완결성 문제를 해결해야 하며 많은 노드가 네트워크에 참여할 수 있어야 합니다. 이를 위해 Klaytn은 최적화된 버전의 Istanbul BFT를 사용하고 있습니다. 이는 블록체인 네트워크의 특성을 반영하여 변형된 버전의 PBFT입니다.

Klaytn에는 컨센서스 노드(CN), 프록시 노드(PN) 및 엔드포인트 노드(EN)라는 세 가지 유형의 노드가 있습니다. CN은 CCO(Core Cell Operators)에 의해 관리되며 블록 생성을 담당합니다. 이 블록은 네트워크의 모든 노드에서 검증됩니다. 이 네트워크 토폴로지를 더 알고 싶으시면, [여기](/content/klaytn#klaytn-network-topology)를 확인해주세요.

![Network topology](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-f666dbbc32e51801b8dba9fa3c65fe2092904590%2Fklaytn_network_node.png?alt=media)

Klaytn은 Istanbul BFT를 채택하고, 개선함으로써 빠른 완결성을 보장합니다. 각 블록에 대해 검증 및 합의가 수행되므로 포크가 없고, 합의가 이루어지면 블록의 완결성이 즉시 보장되기 때문입니다.

또한, BFT 알고리즘의 통신량 증가 문제는 임의로 선택된 `위원회(Committee)`를 활용하여 해결됩니다. CN은 함께 `카운슬`을 구성하고, 각 블록 생성시 VRF(Verifiable Random Function)을 이용하여 위원회의 멤버로 선택됩니다.

![Concept of council and committee](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-b3448bffe0198f17be9be2f66f9081ab1509b4be%2Fcouncil-committee.png?alt=media)

합의 메세지는 오직 위원회 멤버들 사이에 교환이 이루어지므로 총 CN의 숫자가 늘더라도 통신량은 제한될 수 있습니다.

현재 Klaytn Mainnet Cypress는 1초의 블록 생성 간격을 가지며 초당 4,000개의 트랜잭션을 처리할 수 있습니다. 현재 50개 이상의 컨센서스 노드가 CNN(Consensus Node Network)에 참여할 수 있으며, Klaytn이 계속해서 알고리즘을 적극적으로 최적화함에 따라 그 수는 지속해서 증가할 예정입니다.


# 계정

## Klaytn 계정 <a href="#klaytn-accounts" id="klaytn-accounts"></a>

### 계정(account), 상태(state), 주소(adress)에 대한 개요 <a href="#overview-of-account-state-and-address" id="overview-of-account-state-and-address"></a>

Klaytn의 계정(account)은 개인의 잔액이나 스마트 컨트랙트에 관한 정보를 포함하는 데이터 구조입니다. Klaytn의 상태(state)는 모든 계정의 상태, 즉 Klaytn의 계정들에 저장된 모든 데이터의 과거와 현재 상태를 의미합니다. Klaytn 노드에서 트랜잭션이 실행되면, Klaytn의 상태는 모든 노드에서 변경됩니다. Klaytn의 노드들이 같은 블록들을 같은 순서대로 처리했다면 Klaytn의 상태는 Klaytn 네트워크의 모든 노드에서 동일해야 합니다. 각 계정의 상태 정보는 각 계정의 식별에 사용되는 20바이트 주소로 참조할 수 있습니다.

### 주소로부터 키 쌍(key pairs) 분리하기 <a href="#decoupling-key-pairs-from-addresses" id="decoupling-key-pairs-from-addresses"></a>

일반적인 블록체인 플랫폼의 계정은 다음과 같은 특정 길이의 암호화된 주소와 연결되어있습니다 "0x0fe2e20716753082222b52e753854f40afddffd2". 이 주소는 키 쌍(key pair)과 강하게 결합되어 있습니다. 키 쌍이 선택된 경우, 주소는 공개 키에서 파생됩니다. 이는 사용자 경험 측면에서 많은 단점을 가지고 있습니다. 몇가지 단점의 예시는 다음과 같습니다.

* 사용자가 원하는 주소를 가질 수 없습니다.
* 보안성을 향상하기 위해 여러 키 쌍을 사용할 수 없습니다.
* 개인키가 노출되었을 때나 사용자가 주기적으로 보안성 향상을 위해 개인키를 변경하고 싶을 때 키 쌍을 변경할 수 없습니다.

이런 단점들은 블록체인 플랫폼에서 사용자가 주소를 식별자로 생각할 수 없게 만드는 큰 장애물입니다. 이 문제를 해결하기 위해 클레이튼은 사용자가 자신의 주소와 키 쌍을 선택할 수 있도록 하는 기능을 제공합니다. 이 기능으로 사용자는 원하는 주소를 선택할 수 있고, 다중 키 쌍을 사용하여 보안을 강화할 수 있습니다. 키 쌍의 수는 하나 이상이 될 수 있으며, 키 쌍은 각기 다른 역할을 할 수 있습니다. 다중 키 쌍과 역할기반 키에 대한 상세 내용은 [다중 키 쌍과 역할기반 키](#multiple-key-pairs-and-role-based-keys)를 참고해주세요.

Klatn은 키 쌍과 주소가 강하게 결합되어 있는 전통적인 방식 또한 지원한다는 사실도 기억해주세요.

### 다중 키 쌍과 역할기반 키 <a href="#multiple-key-pairs-and-role-based-keys" id="multiple-key-pairs-and-role-based-keys"></a>

앞에서 설명한 것처럼 개인 키를 도난당하거나, 개인 키가 노출된 경우 다시 계정을 안전한 상태로 되돌릴 방법이 없습니다. 가장 좋은 방법은 다른 키 쌍을 생성하여 새 계정을 만들고 기존 계정에서 잔액을 옮기는 것입니다. 다중 서명 또는 용도별 키와 같은 고급 키 체계가 지원되지 않으면 매우 불편합니다. 이러한 문제를 더욱 효율적으로 해결하기 위해 Klaytn 계정은 다음 기능을 제공합니다.

* Klaytn 계정은 키 쌍과 연결되는데, 이 키 쌍은 변경될 수 있습니다.
* Klaytn 계정은 다중 키 쌍을 지원하며, 각 키는 다른 목적을 가지도록 할 수 있습니다.
* Klaytn 계정은 주소와 강하게 결합된 단일키를 가진 계정과 호환됩니다.

Klaytn 계정의 역할 기반 키나 다중 키 기능을 이용하여, 사용자는 실생활에서 일어날 수 있는 개인키 노출 등 여러 보안 위협에 더욱 잘 대처할 수 있습니다. 예를 들어, 사용자가 자신의 개인키가 노출되었다는 것을 알게 되면 사용자는 자신의 계정에서 노출된 키 쌍을 제거하고 새키 쌍을 만들어 노출된 개인키와 간단히 교체 할 수 있습니다. 키 교체 작업을 위해서 미리 생성된 계정 정보 업데이트용 키를 이용할 수 있습니다. 이 키는 노출된 개인키와 따로 저장되어있어서 노출되지 않았어야 안전하게 이용할 수 있습니다.

### Human-Readable Address (HRA) <a href="#human-readable-address-hra" id="human-readable-address-hra"></a>

블록체인 플랫폼의 주소 체계 (예 : "0x0fe2e20716753082222b52e753854f40afddffd2")는 계정 소유자의 개인 정보를 효율적으로 보호한다는 점에서 장점이 있지만, 사용자 경험 측면에서는 매우 불편합니다. 첫째, 인간의 두뇌는 이런 주소를 암기하거나 인식하기 어려워하기 때문에, 이런 주소 체계는 입력 실수 같은 다양한 인적 오류를 유발하여 중대한 재정적 손해를 입힐 수도 있습니다. 둘째, 이런 주소 체계는 사용자가 선호하는 사용하거나 기억하기 쉬운 주소를 선택할 기회를 뺏어갑니다. Combined, these problems are among the toughest usability hurdles that cause dApp user experience for typical end-users (who are more accustomed to the simpler, frictionless user experience offered by legacy mobile apps or services) to be perceived as alien, incomprehensible, and severely inconvenient. To overcome such challenges without undergoing architectural modifications at large-scale and while preserving backward compatibility, Klaytn opts to provide a mapping between a 20-byte address to a 20-byte length text string that end-users could assign their own preferred values to. 이 기능은 human-readable address (HRA)라고 불립니다. 이 기능은 현재 개발 중이며 준비가 되면 더 많은 정보가 제공될 것입니다.

### Klaytn 지갑 키 형식 <a href="#klaytn-wallet-key-format" id="klaytn-wallet-key-format"></a>

Klaytn wallet 키 형식은 해당 주소와 함께 개인키를 쉽게 다룰 수 있도록 만들어졌습니다. 이는 사용자가 개인키를 주소와 함께 관리하기 쉽게 만듭니다. 이 형식은 `0x{private key}0x{type}0x{address in hex}`입니다. 16진법을 따르며, `{type}`은 `00`여야 합니다. 다른 값은 예약되어 있습니다. 예시는 다음과 같습니다.

```
0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d80x000xa94f5374fce5edbc8e2a8697c15331677e6ebf0b
```

이 형식은 현재 [Klaytn Wallet](/content/dapp/developer-tools/getting-started/klaytn-wallet)에서 지원됩니다.

### Klaytn 계정 유형 <a href="#klaytn-account-types" id="klaytn-account-types"></a>

Klaytn에는 두 가지 유형의 계정이 있습니다 : 외부 소유 계정 (EOAs) 및 스마트 컨트랙트 계정(SCAs)

#### 외부 소유 계정 (EOAs) <a href="#externally-owned-accounts-eoas" id="externally-owned-accounts-eoas"></a>

외부 소유 계정에는 논스(nonce) 및 잔고와 같은 정보가 있습니다. 이 유형의 계정에는 코드 또는 스토리지가 없습니다. EOA는 개인키로 제어되며 관련 코드를 가지지 않습니다. EOA는 키 페어를 사용하여 생성되고, 키 페어를 가진 어떤 사람이든 EOA를 제어 할 수 있습니다. 계정키는 [Account Key](#account-key) 장에 설명되어있습니다.

**속성**

| 속성            | Type                       | Description                                                                                                                                                                                                                                                                          |
| ------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| type          | uint8 (Go)                 | EOA의 유형입니다. EOA의 경우 Type은 **0x1**이어야 합니다.                                                                                                                                                                                                                                            |
| nonce         | uint64 (Go)                | 트랜잭션의 순서를 정하기 위한 시퀀스 번호(Sequence number). 다음 처리 될 트랜잭션은 이 값과 같은 Nonce값을 가집니다.                                                                                                                                                                                                        |
| balance       | \*big.Int (Go)             | 계정이 가지고 있는 Klay의 양                                                                                                                                                                                                                                                                   |
| humanReadable | bool (Go)                  | 계정이 Human-readable address와 연결되어있는지 알려주는 Boolean 값 [HRA](#human-readable-address-hra)은 현재 개발중이므로, 이 값은 모든 계정에서 false로 지정되어있습니다.                                                                                                                                                      |
| key           | [AccountKey](#account-key) | 이 계정과 연결된 키. 이 필드는 [AccountKeyLegacy](#accountkeylegacy), [AccountKeyPublic](#accountkeypublic), [AccountKeyFail](#accountkeyfail), [AccountKeyWeightedMultisig](#accountkeyweightedmultisig), [AccountKeyRoleBased](#accountkeyrolebased) 중 어떤 것이라도 될 수 있습니다. 트랜잭션의 서명은 이 키로 검증됩니다. |

#### 스마트 컨트랙트 계정 (SCAs) <a href="#smart-contract-accounts-scas" id="smart-contract-accounts-scas"></a>

EOA와 달리 SCA에는 관련 코드가 있으며 해당 코드로 제어됩니다. SCA는 스마트 컨트랙트 배포(deployment) 트랜잭션에 의해 생성됩니다. 일단 배포되면 SCA는 자체적으로 새 트랜잭션을 시작할 수 없으며, EOA 또는 다른 SCA나 다른 계정에 의해 작동되어야합니다.

**Attributes**

| Attribute     | Type                       | Description                                                                                                                                                                                                                                                                                                                                    |
| ------------- | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| type          | uint8 (Go)                 | 스마트 컨트랙트 계정의 유형입니다. SCA의 경우 Type은 **0x2**이어야 합니다.                                                                                                                                                                                                                                                                                              |
| nonce         | uint64 (Go)                | A sequence number used to determine the order of transactions. The transaction to be processed next has the same nonce with this value.                                                                                                                                                                                                        |
| balance       | \*big.Int (Go)             | The amount of KLAY the account has.                                                                                                                                                                                                                                                                                                            |
| humanReadable | bool (Go)                  | A boolean value indicating that the account is associated with a human-readable address. Since [HRA](#human-readable-address-hra) is under development, this value is false for all accounts.                                                                                                                                                  |
| key           | [AccountKey](#account-key) | The key associated with this account. This field can be any of [AccountKeyLegacy](#accountkeylegacy), [AccountKeyPublic](#accountkeypublic), [AccountKeyFail](#accountkeyfail), [AccountKeyWeightedMultisig](#accountkeyweightedmultisig), [AccountKeyRoleBased](#accountkeyrolebased). Signatures in transactions are verified with this key. |
| codeHash      | \[]byte (Go)               | 계정의 스마트 컨트랙트 코드의 해시. 이 값은 변경할 수 없으며, 스마트 컨트랙트가 생성 될 때만 설정됩니다.                                                                                                                                                                                                                                                                                  |
| storageRoot   | \[32]byte (Go)             | 계정에 저장된 모든 변수들의 값을 포함하는 Merkle Patricia trie 루트의 256비트 해시입니다.                                                                                                                                                                                                                                                                                  |
| codeFormat    | uint8 (Go)                 | 계정이 지원하는 interpreter 버전입니다. 16까지 설정할 수 있으며, 현재는 EVM(0x00)만 지원합니다.                                                                                                                                                                                                                                                                              |
| vmVersion     | uint8 (Go)                 | The protocol upgrade (hard fork) information at contract deployment time (ex. 0x0(constantinople), 0x1(istanbul,london,...)). 16까지 존재하며, 컨트랙트 배포 시 자동으로 값이 설정됩니다.                                                                                                                                                                              |

{% hint style="success" %}
NOTE: Klaytn v1.7.0부터는 스마트 컨트랙트 계정의 속성으로 vmVersion이 추가됩니다.
{% endhint %}

### Klaytn 계정 유형 ID <a href="#klaytn-account-type-id" id="klaytn-account-type-id"></a>

아래는 각 계정 유형에 할당된 계정 유형 ID입니다.

| 계정 유형              | 계정 유형 ID |
| ------------------ | -------- |
| 외부 소유 계정 (EOAs)    | 0x1      |
| 스마트 컨트랙트 계정 (SCAs) | 0x2      |

## 계정 키 <a href="#account-key" id="account-key"></a>

An account key represents the key structure associated with an account.

### AccountKeyNil <a href="#accountkeynil" id="accountkeynil"></a>

AccountKeyNil은 빈(empty) 키를 나타냅니다. 계정이 AccountKeyNil object를 가지려고 하면 트랜잭션은 실패합니다. AccountKeyNil은 역할기반 키(role-based keys)를 이용하는 TxTypeAccountUpdate 트랜잭션에만 사용됩니다. 예를 들어, 계정이 RoleAccountUpdate 키만 업데이트하려고 할 때TxTypeAccountUpdate 트랜잭션의 키 필드는 다음과 같습니다.

`[AccountKeyNil, NewKey, AccountKeyNil]`

그런 다음 RoleAccountUpdate 키만 업데이트됩니다. 다른 역할은 업데이트되지 않습니다. 상세사항을 알고 싶으시면 [AccountKeyRoleBased](#accountkeyrolebased)를 참고해주세요.

#### 속성 <a href="#attributes" id="attributes"></a>

AccountKeyNil에 대한 속성이 없습니다.

#### RLP 인코딩 <a href="#rlp-encoding" id="rlp-encoding"></a>

`0x80`

### AccountKeyLegacy <a href="#accountkeylegacy" id="accountkeylegacy"></a>

AccountKeyLegacy는 해당 키 쌍에서 파생된 주소를 가진 계정에 사용됩니다. 계정이 AccountKeyLegacy를 가지고 있는 경우, 트랜잭션 유효성 검사 절차는 다음과 같이 수행됩니다. 일반적인 블록체인 플랫폼의 절차와 같습니다.

* 공개키를 `ecrecover(txhash, txsig)`로부터 얻습니다.
* 공개키의 주소를 얻습니다.
* 주소는 발신자입니다.

#### Attributes <a href="#attributes" id="attributes"></a>

| Attribute | Type       | Description                                  |
| --------- | ---------- | -------------------------------------------- |
| Type      | uint8 (Go) | AccountKeyLegacy의 유형입니다. 이는 **0x01**이어야 합니다. |

#### RLP Encoding <a href="#rlp-encoding" id="rlp-encoding"></a>

`0x01c0`

### AccountKeyPublic <a href="#accountkeypublic" id="accountkeypublic"></a>

AccountKeyPublic is used for accounts having one public key.\
If an account has an AccountKeyPublic object, the transaction validation process is done like below:

* `ecrecover(txhash, txsig)`로부터 파생된 공개키를 얻습니다.
* 파생된 공개키가 해당 계정의 공개키와 같은지 확인합니다.

#### Attributes <a href="#attributes" id="attributes"></a>

| Attribute | Type           | Description                                    |
| --------- | -------------- | ---------------------------------------------- |
| Type      | uint8 (Go)     | AccountKeyPublic의 유형입니다. 이는 **0x02**가 되어야 합니다. |
| Key       | \[33]byte (Go) | 키는 S256 곡선에서 압축된 공개키여야 합니다.                    |

#### RLP Encoding <a href="#rlp-encoding" id="rlp-encoding"></a>

`0x02 + encode(CompressedPubKey)`

**참고**: CompressedPubKey는 [SEC1](https://www.secg.org/SEC1-Ver-1.0.pdf)에 정의된 압축된 형식의 공개키입니다. 즉, PubkeyY가 짝수이면 0x02{PubkeyX} 이고, 그렇지 않으면 0x03{PubkeyX} 입니다.

#### RLP 인코딩 (예시) <a href="#rlp-encoding-example" id="rlp-encoding-example"></a>

```javascript
prvkey 0xf8cc7c3813ad23817466b1802ee805ee417001fcce9376ab8728c92dd8ea0a6b
pubkeyX 0xdbac81e8486d68eac4e6ef9db617f7fbd79a04a3b323c982a09cdfc61f0ae0e8
pubkeyY 0x906d7170ba349c86879fb8006134cbf57bda9db9214a90b607b6b4ab57fc026e

RLP: 0x02a102dbac81e8486d68eac4e6ef9db617f7fbd79a04a3b323c982a09cdfc61f0ae0e8
```

### AccountKeyFail <a href="#accountkeyfail" id="accountkeyfail"></a>

계정에 AccountKeyFail 키가 있으면 트랜잭션 유효성 검증 프로세스는 항상 실패하게 됩니다. 특정 스마트 컨트랙트 계정에서 전송된 트랜잭션이 항상 실패하도록 사용될 수 있습니다.

#### Attributes <a href="#attributes" id="attributes"></a>

| Attribute | Type       | Description                                   |
| --------- | ---------- | --------------------------------------------- |
| Type      | uint8 (Go) | AcccountKeyFail의 유형입니다. 이는 **0x03**가 되어야 합니다. |

#### RLP Encoding <a href="#rlp-encoding" id="rlp-encoding"></a>

`0x03c0`

### AccountKeyWeightedMultiSig <a href="#accountkeyweightedmultisig" id="accountkeyweightedmultisig"></a>

AccountKeyWeightedMultiSig는 계정 키 타입입니다. 여기에는 threshold와 WeightedPublicKeys가 저장되어 있습니다. WeightedPublicKeys는 공개키와 공개키의 가중치(weight)로 이루어진 리스트입니다. AccountKeyWeightedMultiSig와 연결된 계정에 대해 유효한 트랜잭션이 되려면, 다음 조건을 만족해야합니다.

* 서명된 공개키의 가중치 합계가 임계값(threshold)보다 커야합니다.
* 트랜잭션에 유효하지 않은 서명이 포함되면 안 됩니다.
* 서명된 공개키 개수가 WeightedPublicKey 개수보다 적어야만 합니다.

{% hint style="success" %}
NOTE: The following multiSig validation logic has changed with the `IstanbulEVM` protocol upgrade, or the "hard fork".

* The invalid signature should not be included in the transaction.
* The number of signed public keys should be less than the number of weightedPublicKeys. If you want the previous document, please refer to [previous document](/content/klaytn/design/transaction-fees/transaction-fees-previous).

`IstanbulEVM` protocol upgrade block number is as follows.

* Baobab Testnet: `#75373312`
* Cypress Mainnet: `#86816005`
  {% endhint %}

#### Attributes <a href="#attributes" id="attributes"></a>

| Attribute          | Type                      | Description                                                                                             |
| ------------------ | ------------------------- | ------------------------------------------------------------------------------------------------------- |
| Type               | uint8 (Go)                | AccountKeyWeightedMultiSig의 유형입니다. 이는 **0x04**이어야 합니다.                                                  |
| Threshold          | uint (Go)                 | 검증 임계값(threshold) 유효한 거래가 되려면 서명의 가중치(weight) 합계가 임계값(threshold) 이상이어야합니다.                              |
| WeightedPublicKeys | \[]{uint, \[33]byte} (Go) | 가중 공개키 목록(A list of weighted public keys). 가중 공개키(weighted public key)에는 압축된 공개키와 그 가중치(weight)가 포함됩니다. |

#### RLP Encoding <a href="#rlp-encoding" id="rlp-encoding"></a>

`0x04 + encode([threshold, [[weight, CompressedPubKey1], [weight2, CompressedPubKey2]]])`

#### RLP Encoding (Example) <a href="#rlp-encoding-example" id="rlp-encoding-example"></a>

```javascript
Threshold 3
Key0 Weight: 1
PubkeyX 0xc734b50ddb229be5e929fc4aa8080ae8240a802d23d3290e5e6156ce029b110e
PubkeyY 0x61a443ac3ffff164d1fb3617875f07641014cf17af6b7dc38e429fe838763712
Key1 Weight: 1
PubkeyX 0x12d45f1cc56fbd6cd8fc877ab63b5092ac77db907a8a42c41dad3e98d7c64dfb
PubkeyY 0x8ef355a8d524eb444eba507f236309ce08370debaa136cb91b2f445774bff842
Key2 Weight: 1
PubkeyX 0xea9a9f85065a00d7b9ffd3a8532a574035984587fd08107d8f4cbad6b786b0cd
PubkeyY 0xb95ebb02d9397b4a8faceb58d485d612f0379a923ec0ddcf083378460a56acca
Key3 Weight: 1
PubkeyX 0x8551bc489d62fa2e6f767ba87fe93a62b679fca8ff3114eb5805e6487b51e8f6
PubkeyY 0x4206aa84bc8955fcbfcc396854228aa63ebacd81b7311a31ab9d71d90b7ec3d7

RLP: 0x04f89303f890e301a102c734b50ddb229be5e929fc4aa8080ae8240a802d23d3290e5e6156ce029b110ee301a10212d45f1cc56fbd6cd8fc877ab63b5092ac77db907a8a42c41dad3e98d7c64dfbe301a102ea9a9f85065a00d7b9ffd3a8532a574035984587fd08107d8f4cbad6b786b0cde301a1038551bc489d62fa2e6f767ba87fe93a62b679fca8ff3114eb5805e6487b51e8f6
```

### AccountKeyRoleBased <a href="#accountkeyrolebased" id="accountkeyrolebased"></a>

AccountKeyRoleBased represents a role-based key. The roles are specified at [Roles](#roles).

#### Attributes <a href="#attributes" id="attributes"></a>

| Attribute | Type                 | Description                                                                                                      |
| --------- | -------------------- | ---------------------------------------------------------------------------------------------------------------- |
| Type      | uint8 (Go)           | AccountKeyRoleBased의 유형입니다. 이는 **0x05**이어야 합니다.                                                                  |
| Keys      | \[]{AccountKey} (Go) | 키 목록. 키는 AccountKeyNil, AccountKeyLegacy, AccountKeyPublic, AccountKeyFail 및 AccountKeyWeightedMultiSig 중 하나입니다. |

#### 역할 <a href="#roles" id="roles"></a>

Roles of AccountKeyRoleBased are defined as below:

| 역할                | Description                                                                                                                    |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| RoleTransaction   | Index 0. 기본키. TxTypeAccountUpdate 이외의 트랜잭션은 이 역할의 키로 서명해야합니다.                                                                  |
| RoleAccountUpdate | Index 1. TxTypeAccountUpdate 트랜잭션은 이 키로 서명되어야 합니다. 이 키가 계정에 없으면, RoleTransaction 키를 사용하여 TxTypeAccountUpdate 트랜잭션의 유효성이 검사됩니다. |
| RoleFeePayer      | Index 2. 이 계정이 발신자 대신 트랜잭션 수수료를 보내려면 이 키로 트랜잭션에 서명해야합니다. 이 키가 계정에 없으면 RoleTransaction 키를 사용하여 수수료 위임 트랜잭션의 유효성이 검사됩니다.         |

#### RLP Encoding <a href="#rlp-encoding" id="rlp-encoding"></a>

`0x05 + encode([key1, key2, key3])`

Note that key1, key2, and key3 can be any of above keys (AccountKeyNil, AccountKeyLegacy, AccountKeyPublic, AccountKeyFail, and AccountKeyWeightedMultiSig).

#### Omissible and Expandable Roles <a href="#omissible-and-expandable-roles" id="omissible-and-expandable-roles"></a>

The roles can be omitted from the last index, and the omitted roles are mapped to the first role. However, a role in the middle cannot be omitted, which means RoleTransaction and RoleFeePayer cannot be set without RoleAccountUpdate. For example, if a role-based key is set to `0x05 + encode([key1, key2])`, RoleFeePayer works as if the key is set like `0x05 + encode([key1, key2, key1])`.

This feature allows for more roles to be added in the future. If a new role is provided, the new role of accounts already created with old roles is mapped to the first role.

#### RLP Encoding (Example) <a href="#rlp-encoding-example" id="rlp-encoding-example"></a>

```javascript
RoleTransaction Key
PubkeyX 0xe4a01407460c1c03ac0c82fd84f303a699b210c0b054f4aff72ff7dcdf01512d
PubkeyY 0x0a5735a23ce1654b14680054a993441eae7c261983a56f8e0da61280758b5919
RoleAccountUpdate Key
Threshold: 2
Key0 Weight:1
PubkeyX 0xe4a01407460c1c03ac0c82fd84f303a699b210c0b054f4aff72ff7dcdf01512d
PubkeyY 0x0a5735a23ce1654b14680054a993441eae7c261983a56f8e0da61280758b5919
Key1 Weight:1
PubkeyX 0x36f6355f5b532c3c1606f18fa2be7a16ae200c5159c8031dd25bfa389a4c9c06
PubkeyY 0x6fdf9fc87a16ac359e66d9761445d5ccbb417fb7757a3f5209d713824596a50d
RoleFeePayer Key
PubkeyX 0xc8785266510368d9372badd4c7f4a94b692e82ba74e0b5e26b34558b0f081447
PubkeyY 0x94c27901465af0a703859ab47f8ae17e54aaba453b7cde5a6a9e4a32d45d72b2

RLP: 0x05f898a302a103e4a01407460c1c03ac0c82fd84f303a699b210c0b054f4aff72ff7dcdf01512db84e04f84b02f848e301a103e4a01407460c1c03ac0c82fd84f303a699b210c0b054f4aff72ff7dcdf01512de301a10336f6355f5b532c3c1606f18fa2be7a16ae200c5159c8031dd25bfa389a4c9c06a302a102c8785266510368d9372badd4c7f4a94b692e82ba74e0b5e26b34558b0f081447
```

## 계정 키 유형 ID <a href="#account-key-type-id" id="account-key-type-id"></a>

Below are the Account Key Type ID assigned to each Account Key Type.

| 계정 키 유형                    | 계정 키 유형 ID |
| -------------------------- | ---------- |
| AccountKeyLegacy           | 0x01       |
| AccountKeyPublic           | 0x02       |
| AccountKeyFail             | 0x03       |
| AccountKeyWeightedMultiSig | 0x04       |
| AccountKeyRoleBased        | 0x05       |


# 트랜잭션

## 트랜잭션 개요 <a href="#transactions-overview" id="transactions-overview"></a>

A transaction in a blockchain platform is a message sent between nodes that changes the state of the blockchain. 예를 들어 Alice의 계정에서 Bob의 계정으로 10 KLAY를 보내는 트랜잭션이 실행될 때 Alice의 잔액은 10 KLAY 감소하고 Bob의 잔액은 10 KLAY 증가합니다. 한 트랜잭션이 다른 트랜잭션 사이에 낄 수 없습니다. 트랜잭션은 아토믹(atomic) 연산이기 때문입니다 일반적인 블록체인 트랜잭션에는 다음과 같은 구성 요소가 있습니다.

| 구성요소     | Description                                                                                                                                                                                                                                            |
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| value    | 명시된 양의 KLAY(단위: peb)가 전송됩니다.                                                                                                                                                                                                                           |
| to       | The account address that will receive the transferred value.                                                                                                                                                                                           |
| input    | Data attached to the transaction, used for transaction execution.                                                                                                                                                                                      |
| v, r, s  | 수신자가 발신자의 주소를 받을 수 있게 발신자에 의해 발생된 암호학적 서명입니다.                                                                                                                                                                                                          |
| nonce    | 발신자의 트랜잭션을 고유하게 식별하기 위해 사용되는 값입니다. 발신자가 동일한 논스를 가진 두 개의 트랜잭션을 생성하면 하나만 실행됩니다.                                                                                                                                                                          |
| gas      | The maximum amount of transaction fee the transaction is allowed to use.                                                                                                                                                                               |
| gasPrice | 발신자가 얼마나 가스비를 지급해야하는지 알 수 있도록 곱하는 값입니다. 발신자가 지급해야할 비용은 `gas` \* `gasPrice`로 계산됩니다. 예를 들어, 만약 가스가 10이 필요하고 gasPrice가 10^18이라면 발신자는 트랜잭션을 위해 10 KLAY를 지급해야 합니다. KLAY의 단위는 [여기](/content/klaytn/design/klaytn-native-coin-klay#units-of-klay)에 설명되어 있습니다. |

## Klaytn 트랜잭션 <a href="#klaytn-transactions" id="klaytn-transactions"></a>

일반적인 블록체인 플랫폼은 하나의 트랜잭션 유형만 제공합니다. 하지만, Klaytn은 새로운 기능을 제공하고, 메모리 풋 프린트와 퍼포먼스를 최적화하기 위해 여러 가지 트랜잭션 유형을 제공합니다.

### 트랜잭션의 서명 검증 <a href="#signature-validation-of-transactions" id="signature-validation-of-transactions"></a>

일반적인 블록체인 플랫폼에서 주소는 공개키에서 파생되며, 공개키는 트랜잭션 서명에서 다시 파생됩니다. 이런 방식은 주소와 키 쌍이 강력하게 연결된 경우에만 가능합니다.

클레이튼에서 키 쌍은 Klaytn의 주소와 분리되어 있으므로 발신자 주소는 트랜잭션 서명을 사용하여 파생되지 않습니다. 이것이 TxTypeLegacyTransaction을 제외한 다른 Klaytn 트랜잭션 유형의 필드에 `from`이 있는 이유입니다. 트랜잭션을 검증하기 위해 클레이튼에서 `from`의 [AccountKey](/content/klaytn/design/accounts#account-key)가 사용됩니다.

### Fee Delegation <a href="#fee-delegation" id="fee-delegation"></a>

Klaytn은 비즈니스 모델 디자인에 유연성을 제공하기 위해 기본 트랜잭션 유형들에 대한 여러 가지 비용 위임 버전을 제공합니다. 이러한 변형을 통해 서비스 제공자가 대신 트랜잭션 수수료를 지불하여 최종 사용자 활동에 보조금을 지급할 수 있습니다. 트랜잭션 수수료 보조금은 Ratio parameter를 조정하여 서비스 제공자가 커버할 수수료의 비율을 정할 수 있습니다. 트랜잭션 수수료 위임 트랜잭션은 적어도 두 개의 서명이 필요하다. 하나는 발신자로부터, 또 다른 하나는 트랜잭션 수수료 지불인으로부터의 서명이다.

### SenderTxHash <a href="#sendertxhash" id="sendertxhash"></a>

SenderTxHash는 트랜잭션 수수료 납부자의 주소와 서명이 없는 트랜잭션의 해시입니다. 트랜잭션 수수료 위임 트랜잭션의 트랜잭션 해시는 수수료 지불인이 그 거래에 서명할 때까지 결정되지 않는다. 수수료 위임 트랜잭션을 찾으려면 발신자는 발신자와 트랜잭션 수수료 지불인 모두의 서명이 담긴 완전한 트랜잭션으로부터 파생된 트랜잭션 해시를 얻어야 합니다. 발신자가 트랜잭션 해시를 얻는 것이 매우 어렵기 때문에 Klaytn은 트랜잭션 해시뿐만 아니라 SenderTxHash를 제공합니다. Klaytn 네트워크에서 완전한 수수료 위임 트랜잭션을 찾으려면 발신자는 SenderTxHash을 만들고 트랜잭션 오브젝트를 [klay\_getTransactionBySenderTxHash](https://github.com/klaytn/klaytn-docs-ko/blob/main/docs/bapp/json-rpc/api-references/klay/transaction.md#klay_gettransactionbysendertxhash)로 요청해야 합니다. SenderTxHash를 얻기 위한 방법은 트랜잭션 유형에 따라 다릅니다. 관련 내용은 각 트랜잭션 유형의 설명을 참고하세요.

각 트랜잭션 유형을 자세하게 살펴보면 다음과 같습니다.

|                        | Basic                                                                                                  | Fee Delegation                                                                                                                          | Partial Fee Delegation                                                                                                                                            |
| ---------------------- | ------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Legacy                 | [TxTypeLegacyTransaction](/content/klaytn/design/transactions/basic#txtypelegacytransaction)           | N/A                                                                                                                                     | N/A                                                                                                                                                               |
| ValueTransfer          | [TxTypeValueTransfer](/content/klaytn/design/transactions/basic#txtypevaluetransfer)                   | [TxTypeFeeDelegatedValueTransfer](/content/klaytn/design/transactions/fee-delegation#txtypefeedelegatedvaluetransfer)                   | [TxTypeFeeDelegatedValueTransferWithRatio](/content/klaytn/design/transactions/partial-fee-delegation#txtypefeedelegatedvaluetransferwithratio)                   |
| ValueTransferMemo      | [TxTypeValueTransferMemo](/content/klaytn/design/transactions/basic#txtypevaluetransfermemo)           | [TxTypeFeeDelegatedValueTransferMemo](/content/klaytn/design/transactions/fee-delegation#txtypefeedelegatedvaluetransfermemo)           | [TxTypeFeeDelegatedValueTransferMemoWithRatio](/content/klaytn/design/transactions/partial-fee-delegation#txtypefeedelegatedvaluetransfermemowithratio)           |
| SmartContractDeploy    | [TxTypeSmartContractDeploy](/content/klaytn/design/transactions/basic#txtypesmartcontractdeploy)       | [TxTypeFeeDelegatedSmartContractDeploy](/content/klaytn/design/transactions/fee-delegation#txtypefeedelegatedsmartcontractdeploy)       | [TxTypeFeeDelegatedSmartContractDeployWithRatio](/content/klaytn/design/transactions/partial-fee-delegation#txtypefeedelegatedsmartcontractdeploywithratio)       |
| SmartContractExecution | [TxTypeSmartContractExecution](/content/klaytn/design/transactions/basic#txtypesmartcontractexecution) | [TxTypeFeeDelegatedSmartContractExecution](/content/klaytn/design/transactions/fee-delegation#txtypefeedelegatedsmartcontractexecution) | [TxTypeFeeDelegatedSmartContractExecutionWithRatio](/content/klaytn/design/transactions/partial-fee-delegation#txtypefeedelegatedsmartcontractexecutionwithratio) |
| AccountUpdate          | [TxTypeAccountUpdate](/content/klaytn/design/transactions/basic#txtypeaccountupdate)                   | [TxTypeFeeDelegatedAccountUpdate](/content/klaytn/design/transactions/fee-delegation#txtypefeedelegatedaccountupdate)                   | [TxTypeFeeDelegatedAccountUpdateWithRatio](/content/klaytn/design/transactions/partial-fee-delegation#txtypefeedelegatedaccountupdatewithratio)                   |
| Cancel                 | [TxTypeCancel](/content/klaytn/design/transactions/basic#txtypecancel)                                 | [TxTypeFeeDelegatedCancel](/content/klaytn/design/transactions/fee-delegation#txtypefeedelegatedcancel)                                 | [TxTypeFeeDelegatedCancelWithRatio](/content/klaytn/design/transactions/partial-fee-delegation#txtypefeedelegatedcancelwithratio)                                 |
| ChainDataAnchoring     | [TxTypeChainDataAnchoring](/content/klaytn/design/transactions/basic#txtypechaindataanchoring)         | [TxTypeFeeDelegatedChainDataAnchoring](/content/klaytn/design/transactions/fee-delegation#txtypefeedelegatedchaindataanchoring)         | [TxTypeFeeDelegatedChainDataAnchoringWithRatio](/content/klaytn/design/transactions/partial-fee-delegation#txtypefeedelegatedchaindataanchoringwithratio)         |


# 기본

## TxTypeLegacyTransaction <a href="#txtypelegacytransaction" id="txtypelegacytransaction"></a>

TxTypeLegacyTransaction은 이전에 Klaytn에 존재했던 트랜잭션 유형을 의미합니다. Since this transaction type exists to support compatibility, it only works with EOAs associated with [AccountKeyLegacy](/content/klaytn/design/accounts#accountkeylegacy). 다른 계정 키 유형과 연결된 EOA는 TxTypeValueTransfer, TxTypeSmartContractExecution 같은 다른 트랜잭션 유형을 사용해야 합니다. 이 유형의 트랜잭션은 계정 생성, 토큰 전송, 스마트 컨트랙트 배포, 스마트 컨트랙트 실행 또는 앞에서 언급한 것들을 혼합하여 실행할 수 있습니다. 이 트랜잭션 유형은 다음과 같은 변경 사항을 만듭니다.

1. 발신자의 잔고는 트랜잭션 수수료만큼 줄어듭니다.
2. 발신자의 논스가 1 증가합니다.
3. If `to` does not exist on Klaytn, an EOA associated with [AccountKeyLegacy](/content/klaytn/design/accounts#accountkeylegacy) is created.
4. `value` KLAY가 발신자로부터 수신자로 전송됩니다.
5. `to`가 nil이라면 스마트컨 트랙트 배포를 위한 트랜잭션으로 간주됩니다. 스마트 컨트랙트 코드는 `input`을 통해 전달되어야 합니다.
6. `to`가 스마트 컨트랙트라면 `input`에 명시된 스마트 컨트랙트 함수가 실행됩니다.

### Attributes <a href="#attributes" id="attributes"></a>

| Attribute | Type                  | Description                                                                                                                                                                                                                                                                                                                      |
| --------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| value     | \*big.Int (Go)        | The amount of KLAY in `peb` to be transferred.                                                                                                                                                                                                                                                                                   |
| to        | \*common.Address (Go) | The account address that will receive the transferred value.                                                                                                                                                                                                                                                                     |
| input     | \[]byte (Go)          | Data attached to the transaction, used for transaction execution.                                                                                                                                                                                                                                                                |
| v, r, s   | \*big.Int (Go)        | The cryptographic signature generated by the sender to let the receiver obtain the sender's address.                                                                                                                                                                                                                             |
| nonce     | uint64 (Go)           | A value used to uniquely identify a sender’s transaction. If two transactions with the same nonce are generated by a sender, only one is executed.                                                                                                                                                                               |
| gas       | uint64 (Go)           | The maximum amount of transaction fee the transaction is allowed to use.                                                                                                                                                                                                                                                         |
| gasPrice  | \*big.Int (Go)        | A multiplier to get how much the sender will pay in tokens. The amount of tokens the sender will pay is calculated via `gas` \* `gasPrice`. For example, the sender will pay 10 KLAY for a transaction fee if gas is 10 and gasPrice is 10^18. See [Unit of KLAY](/content/klaytn/design/klaytn-native-coin-klay#units-of-klay). |

### 서명 RLP 인코딩 <a href="#rlp-encoding-for-signature" id="rlp-encoding-for-signature"></a>

이 트랜잭션 유형의 서명을 만들려면 다음과 같이 RLP 직렬화를 수행해야합니다.

```javascript
SigRLP = encode([nonce, gasPrice, gas, to, value, input, chainid, 0, 0])
SigHash = keccak256(SigRLP)
Signature = sign(SigHash, <private key>)
```

### SenderTxHash를 위한 RLP 인코딩 <a href="#rlp-encoding-for-sendertxhash" id="rlp-encoding-for-sendertxhash"></a>

SenderTxHash를 만들려면 다음과 같이 RLP 직렬화를 수행해야합니다.

```javascript
SenderTxHashRLP = encode([nonce, gasPrice, gas, to, value, input, v, r, s])
SenderTxHash = keccak256(SenderTxHashRLP)
```

### 트랜잭션 해시를 위한 RLP 인코딩 <a href="#rlp-encoding-for-transaction-hash" id="rlp-encoding-for-transaction-hash"></a>

트랜잭션 해시를 만들려면 다음과 같이 RLP 직렬화를 수행해야합니다.

```javascript
TxHashRLP = encode([nonce, gasPrice, gas, to, value, input, v, r, s])
TxHash = keccak256(TxHashRLP)
```

### RLP Encoding (Example) <a href="#rlp-encoding-example" id="rlp-encoding-example"></a>

다음은 RLP 직렬화의 결과와 트랜잭션 오브젝트를 보여줍니다.

```javascript
ChainID 0x1
PrivateKey 0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8
PublicKey.X 0x3a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d
PublicKey.Y 0x8072e77939dc03ba44790779b7a1025baf3003f6732430e20cd9b76d953391b3
SigRLP 0xe68204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a8431323334018080
SigHash 0x40e73366650cddb7affcf5af39efa864b2c68c42b5329044fc86a12b26c4edc7
Signature f845f84325a0b2a5a15550ec298dc7dddde3774429ed75f864c82caeb5ee24399649ad731be9a029da1014d16f2011b3307f7bbe1035b6e699a4204fc416c763def6cefd976567
TxHashRLP 0xf8668204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a843132333425a0b2a5a15550ec298dc7dddde3774429ed75f864c82caeb5ee24399649ad731be9a029da1014d16f2011b3307f7bbe1035b6e699a4204fc416c763def6cefd976567
TxHash e434257753bf31a130c839fec0bd34fc6ea4aa256b825288ee82db31c2ed7524
SenderTxHashRLP 0xf8668204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a843132333425a0b2a5a15550ec298dc7dddde3774429ed75f864c82caeb5ee24399649ad731be9a029da1014d16f2011b3307f7bbe1035b6e699a4204fc416c763def6cefd976567
SenderTxHash e434257753bf31a130c839fec0bd34fc6ea4aa256b825288ee82db31c2ed7524

    TX(e434257753bf31a130c839fec0bd34fc6ea4aa256b825288ee82db31c2ed7524)
    Contract: false
    From:     a94f5374fce5edbc8e2a8697c15331677e6ebf0b
    To:       7b65b75d204abed71587c9e519a89277766ee1d0
    Nonce:    1234
    GasPrice: 0x19
    GasLimit  0xf4240
    Value:    0xa
    Data:     0x31323334
    V:        0x25
    R:        0xb2a5a15550ec298dc7dddde3774429ed75f864c82caeb5ee24399649ad731be9
    S:        0x29da1014d16f2011b3307f7bbe1035b6e699a4204fc416c763def6cefd976567
    Hex:      f8668204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a843132333425a0b2a5a15550ec298dc7dddde3774429ed75f864c82caeb5ee24399649ad731be9a029da1014d16f2011b3307f7bbe1035b6e699a4204fc416c763def6cefd976567
```

### RPC Output (예시) <a href="#rpc-output-example" id="rpc-output-example"></a>

다음은 JSON RPC를 통해 반환된 트랜잭션 오브젝트를 보여줍니다.

```javascript
{
  "blockHash": "0xeff95d8c57d668aa274a0eaeff942ecc2cfca4c71f71ae9fdaba92735cd79b9e",
  "blockNumber": "0x1",
  "contractAddress": null,
  "from": "0x33c97827c33d8c5e07eb263ed6ec5c229e8b4752",
  "gas": "0x174876e800",
  "gasPrice": "0x5d21dba00",
  "gasUsed": "0x5208",
  "input": "0x",
  "logs": [],
  "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "nonce": "0x0",
  "senderTxHash": "0xff0e9a45aa8741d528baf84069cd3b52c43a51bf7cf69d896672c3c909507888",
  "signatures": [
    {
      "V": "0x25",
      "R": "0xed8aa552324101a99792860d479cd488b7f67af0b9205968748bddcda52da6de",
      "S": "0x524dbf481ea1d77c20f4d4354cc208c3149ddfa06f7ab53a03ad82d2d7fed3"
    }
  ],
  "status": "0x1",
  "to": "0xd03227635c90c7986f0e3a4e551cefbca8c55316",
  "transactionHash": "0xff0e9a45aa8741d528baf84069cd3b52c43a51bf7cf69d896672c3c909507888",
  "transactionIndex": "0x0",
  "type": "TxTypeLegacyTransaction",
  "typeInt": 0,
  "value": "0x174876e800"
}
```

## TxTypeValueTransfer <a href="#txtypevaluetransfer" id="txtypevaluetransfer"></a>

TxTypeValueTransfer is used when a user wants to send KLAY. Klaytn은 각 목적에 맞는 여러가지 트랜잭션 유형들을 제공하는데, TxTypeValueTransfer는 KLAY를 EOA에 전송할 때 사용하는 기능입니다. 따라서 TxTypeValueTransfer는 `to`가 EOA일때만 작동합니다. KLAY를 스마트 컨트랙트로 전송하려면 [TxTypeSmartContractExecution](#txtypesmartcontractexecution)를 대신 사용하여야 합니다. 이 트랜잭션 유형은 다음과 같은 변경 사항을 만듭니다.

1. The sender's balance decreases by the amount of the transaction fee.
2. The sender's nonce increases by one.
3. `value` KLAY is transferred from the sender to the recipient.

### Attributes <a href="#attributes" id="attributes"></a>

| Attribute    | Type                                      | Description                                                                                                                                                                                                                                 |
| ------------ | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| type         | uint8 (Go)                                | TxTypeValueTransfer의 유형입니다. 이는 0x08이어야 합니다.                                                                                                                                                                                                 |
| nonce        | uint64 (Go)                               | A value used to uniquely identify a sender’s transaction. If two transactions with the same nonce are generated by a sender, only one is executed.                                                                                          |
| gasPrice     | \*big.Int (Go)                            | 발신자가 트랜잭션 수수료로 지불하는 가스의 단가입니다(단위는 peb). 트랜잭션 수수료는 `gas` \* `gasPrice`으로 계산됩니다. 예를 들어, 만약 가스가 10이 필요하고 gasPrice가 10^18이라면 발신자는 트랜잭션을 위해 10 KLAY를 지급해야 합니다. See [Unit of KLAY](/content/klaytn/design/klaytn-native-coin-klay#units-of-klay). |
| gas          | uint64 (Go)                               | 트랜잭션에서 사용하도록 허락된 최대 트랜잭션 수수료입니다.                                                                                                                                                                                                            |
| to           | common.Address (Go)                       | The account address that will receive the transferred value.                                                                                                                                                                                |
| value        | \*big.Int (Go)                            | The amount of KLAY in `peb` to be transferred.                                                                                                                                                                                              |
| from         | common.Address (Go)                       | The address of the sender. 자세한 내용은 [트랜잭션의 서명 검증](/content/klaytn/design/transactions#signature-validation-of-transactions)을 참고해주세요.                                                                                                         |
| txSignatures | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | 발신자의 서명입니다. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                         |

### RLP Encoding for Signature <a href="#rlp-encoding-for-signature" id="rlp-encoding-for-signature"></a>

트랜잭션 서명을 만들려면 다음과 같이 RLP 직렬화를 수행해야합니다.

```javascript
SigRLP = encode([encode([type, nonce, gasPrice, gas, to, value, from]), chainid, 0, 0])
SigHash = keccak256(SigRLP)
Signature = sign(SigHash, <private key>)
```

### RLP Encoding for SenderTxHash <a href="#rlp-encoding-for-sendertxhash" id="rlp-encoding-for-sendertxhash"></a>

To make a SenderTxHash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
SenderTxHashRLP = type + encode([nonce, gasPrice, gas, to, value, from, txSignatures])
SenderTxHash = keccak256(SenderTxHashRLP)
```

### RLP Encoding for Transaction Hash <a href="#rlp-encoding-for-transaction-hash" id="rlp-encoding-for-transaction-hash"></a>

To make a transaction hash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
TxHashRLP = type + encode([nonce, gasPrice, gas, to, value, from, txSignatures])
TxHash = keccak256(TxHashRLP)
```

### RLP Encoding (Example) <a href="#rlp-encoding-example" id="rlp-encoding-example"></a>

다음은 주어진 인수에 대한 RLP 직렬화의 결과와 트랜잭션 오브젝트의 정보를 보여줍니다.

```javascript
ChainID 0x1
PrivateKey 0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8
PublicKey.X 0x3a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d
PublicKey.Y 0x8072e77939dc03ba44790779b7a1025baf3003f6732430e20cd9b76d953391b3
SigRLP 0xf839b5f4088204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0b018080
SigHash 0xaa7665566c9508140bb91e36a948fc8f61c4518400a69562432d17e064f3ce43
Signature f845f84325a0f3d0cd43661cabf53425535817c5058c27781f478cb5459874feaa462ed3a29aa06748abe186269ff10b8100a4b7d7fea274b53ea2905acbf498dc8b5ab1bf4fbc
TxHashRLP 0x08f87a8204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0bf845f84325a0f3d0cd43661cabf53425535817c5058c27781f478cb5459874feaa462ed3a29aa06748abe186269ff10b8100a4b7d7fea274b53ea2905acbf498dc8b5ab1bf4fbc
TxHash 762f130342569e9669a4d8547f1248bd2554fbbf3062d63a97ce28bfa97aa9d7
SenderTxHashRLP 0x08f87a8204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0bf845f84325a0f3d0cd43661cabf53425535817c5058c27781f478cb5459874feaa462ed3a29aa06748abe186269ff10b8100a4b7d7fea274b53ea2905acbf498dc8b5ab1bf4fbc
SenderTxHash 762f130342569e9669a4d8547f1248bd2554fbbf3062d63a97ce28bfa97aa9d7

    TX(762f130342569e9669a4d8547f1248bd2554fbbf3062d63a97ce28bfa97aa9d7)
    Type:          TxTypeValueTransfer
    From:          0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B
    To:            0x7b65B75d204aBed71587c9E519a89277766EE1d0
    Nonce:         1234
    GasPrice:      0x19
    GasLimit:      0xf4240
    Value:         0xa
    Signature:     [{"V":"0x25","R":"0xf3d0cd43661cabf53425535817c5058c27781f478cb5459874feaa462ed3a29a","S":"0x6748abe186269ff10b8100a4b7d7fea274b53ea2905acbf498dc8b5ab1bf4fbc"}]
    Hex:           08f87a8204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0bf845f84325a0f3d0cd43661cabf53425535817c5058c27781f478cb5459874feaa462ed3a29aa06748abe186269ff10b8100a4b7d7fea274b53ea2905acbf498dc8b5ab1bf4fbc
```

### RPC Output (Example) <a href="#rpc-output-example" id="rpc-output-example"></a>

The following shows a transaction object returned via JSON RPC.

```javascript
{
  "blockHash": "0xeff95d8c57d668aa274a0eaeff942ecc2cfca4c71f71ae9fdaba92735cd79b9e",
  "blockNumber": "0x1",
  "contractAddress": null,
  "from": "0x33c97827c33d8c5e07eb263ed6ec5c229e8b4752",
  "gas": "0x174876e800",
  "gasPrice": "0x5d21dba00",
  "gasUsed": "0x5208",
  "logs": [],
  "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "nonce": "0x1",
  "senderTxHash": "0x8c18c9a609d2b22c921ce0b282e64924bf073e84f7c3850d99ec71da4054f79d",
  "signatures": [
    {
      "V": "0x25",
      "R": "0x94e059980bce9f3ba5f09e5021ad4f32d7d9cfda938c2d38c989cd4a406e7ba",
      "S": "0x3ca52ee9d23954a278e6a30f3ec40951b26fb8b3f784c236c5bb1d5c9a8b2c82"
    }
  ],
  "status": "0x1",
  "to": "0x75c3098be5e4b63fbac05838daaee378dd48098d",
  "transactionHash": "0x8c18c9a609d2b22c921ce0b282e64924bf073e84f7c3850d99ec71da4054f79d",
  "transactionIndex": "0x1",
  "type": "TxTypeValueTransfer",
  "typeInt": 8,
  "value": "0x21e19e0c9bab2400000"
}
```

## TxTypeValueTransferMemo <a href="#txtypevaluetransfermemo" id="txtypevaluetransfermemo"></a>

TxTypeValueTransferMemo is used when a user wants to send KLAY with a specific message. 따라서 TxTypeValueTransferMemo는 `to`가 EOA일때만 작동합니다. To transfer KLAY to a smart contract account, use [TxTypeSmartContractExecution](#txtypesmartcontractexecution) instead. The following changes will be made by this transaction type.

1. The sender's balance decreases by the amount of the transaction fee.
2. The sender's nonce increases by one.
3. `value` KLAY is transferred from the sender to the recipient.

### Attributes <a href="#attributes" id="attributes"></a>

| Attribute    | Type                                      | Description                                                                                                                                                                                                                                                                                                                                        |
| ------------ | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| type         | uint8 (Go)                                | TxTypeValueTransferMemo의 유형입니다. 이는 0x10이어야 합니다.                                                                                                                                                                                                                                                                                                    |
| nonce        | uint64 (Go)                               | A value used to uniquely identify a sender’s transaction. If two transactions with the same nonce are generated by a sender, only one is executed.                                                                                                                                                                                                 |
| gasPrice     | \*big.Int (Go)                            | A unit price of gas in `peb` the sender will pay for a transaction fee. The amount of transaction fee is calculated as `gas` \* `gasPrice`. For example, if the transaction consumes 10 units of gas and gasPrice is 10^18, the transaction fee will be 10 KLAY. See [Unit of KLAY](/content/klaytn/design/klaytn-native-coin-klay#units-of-klay). |
| gas          | uint64 (Go)                               | The maximum amount of gas the transaction is allowed to use.                                                                                                                                                                                                                                                                                       |
| to           | common.Address (Go)                       | The account address that will receive the transferred value.                                                                                                                                                                                                                                                                                       |
| value        | \*big.Int (Go)                            | The amount of KLAY in `peb` to be transferred.                                                                                                                                                                                                                                                                                                     |
| from         | common.Address (Go)                       | The address of the sender. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                 |
| input        | \[]byte (Go)                              | Data attached to the transaction. 메시지는 이 속성으로 전달되어야 합니다.                                                                                                                                                                                                                                                                                           |
| txSignatures | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The sender's signatures. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                   |

### RLP Encoding for Signature <a href="#rlp-encoding-for-signature" id="rlp-encoding-for-signature"></a>

To make a transaction signature, RLP serialization should be done like the following:

```javascript
SigRLP = encode([encode([type, nonce, gasPrice, gas, to, value, from, input]), chainid, 0, 0])
SigHash = keccak256(SigRLP)
Signature = sign(SigHash, <private key>)
```

### RLP Encoding for SenderTxHash <a href="#rlp-encoding-for-sendertxhash" id="rlp-encoding-for-sendertxhash"></a>

To make a SenderTxHash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
SenderTxHashRLP = type + encode([nonce, gasPrice, gas, to, value, from, input, txSignatures])
SenderTxHash = keccak256(SenderTxHashRLP)
```

### RLP Encoding for Transaction Hash <a href="#rlp-encoding-for-transaction-hash" id="rlp-encoding-for-transaction-hash"></a>

To make a transaction hash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
TxHashRLP = type + encode([nonce, gasPrice, gas, to, value, from, input, txSignatures])
TxHash = keccak256(TxHashRLP)
```

### RLP Encoding (Example) <a href="#rlp-encoding-example" id="rlp-encoding-example"></a>

The following shows the result of RLP serialization and the transaction object:

```javascript
ChainID 0x1
PrivateKey 0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8
PublicKey.X 0x3a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d
PublicKey.Y 0x8072e77939dc03ba44790779b7a1025baf3003f6732430e20cd9b76d953391b3
SigRLP 0xf841b83cf83a108204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0b8568656c6c6f018080
SigHash 0x23dd6ca2c023a152cad636ac8ed0a1a7962d3eb4cb7f3c50e34c0cc42e37d48a
Signature f845f84325a07d2b0c89ee8afa502b3186413983bfe9a31c5776f4f820210cffe44a7d568d1ca02b1cbd587c73b0f54969f6b76ef2fd95cea0c1bb79256a75df9da696278509f3
TxHashRLP 0x10f8808204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0b8568656c6c6ff845f84325a07d2b0c89ee8afa502b3186413983bfe9a31c5776f4f820210cffe44a7d568d1ca02b1cbd587c73b0f54969f6b76ef2fd95cea0c1bb79256a75df9da696278509f3
TxHash 6c7ee543c24e5b928b638a9f4502c1eca69103f5467ed4b6a2ed0ea5aede2e6b
SenderTxHashRLP 0x10f8808204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0b8568656c6c6ff845f84325a07d2b0c89ee8afa502b3186413983bfe9a31c5776f4f820210cffe44a7d568d1ca02b1cbd587c73b0f54969f6b76ef2fd95cea0c1bb79256a75df9da696278509f3
SenderTxHash 6c7ee543c24e5b928b638a9f4502c1eca69103f5467ed4b6a2ed0ea5aede2e6b

    TX(6c7ee543c24e5b928b638a9f4502c1eca69103f5467ed4b6a2ed0ea5aede2e6b)
    Type:          TxTypeValueTransferMemo
    From:          0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B
    To:            0x7b65B75d204aBed71587c9E519a89277766EE1d0
    Nonce:         1234
    GasPrice:      0x19
    GasLimit:      0xf4240
    Value:         0xa
    Signature:     [{"V":"0x25","R":"0x7d2b0c89ee8afa502b3186413983bfe9a31c5776f4f820210cffe44a7d568d1c","S":"0x2b1cbd587c73b0f54969f6b76ef2fd95cea0c1bb79256a75df9da696278509f3"}]
    Data:          36383635366336633666
    Hex:           10f8808204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0b8568656c6c6ff845f84325a07d2b0c89ee8afa502b3186413983bfe9a31c5776f4f820210cffe44a7d568d1ca02b1cbd587c73b0f54969f6b76ef2fd95cea0c1bb79256a75df9da696278509f3
```

### RPC Output (Example) <a href="#rpc-output-example" id="rpc-output-example"></a>

The following shows a transaction object returned via JSON RPC.

```javascript
{
  "blockHash": "0x7ad6ed1f9955be00db8fb5452125f0e9a3c0856abb5b4cc4aed91ffc134321da",
  "blockNumber": "0x1",
  "contractAddress": null,
  "from": "0x0fcda0f2efbe1b4e61b487701ce4f2f8abc3723d",
  "gas": "0x174876e800",
  "gasPrice": "0x5d21dba00",
  "gasUsed": "0x53fc",
  "input": "0x68656c6c6f",
  "logs": [],
  "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "nonce": "0x4",
  "senderTxHash": "0x7311ef305064f2a6997c16cc8b5fc3fdf301549e7b7d0baa3a995a8e79479e5e",
  "signatures": [
    {
      "V": "0x25",
      "R": "0xd63673e1be7919e7ca42de64931c853fc568557b151e9b335df94b22de3a600f",
      "S": "0x57bc916a50856b4d197f6856f16370f72f3bb0ac411b1da793fdb5bb7066966f"
    }
  ],
  "status": "0x1",
  "to": "0x75c3098be5e4b63fbac05838daaee378dd48098d",
  "transactionHash": "0x7311ef305064f2a6997c16cc8b5fc3fdf301549e7b7d0baa3a995a8e79479e5e",
  "transactionIndex": "0x4",
  "type": "TxTypeValueTransferMemo",
  "typeInt": 16,
  "value": "0x989680"
}
```

## TxTypeSmartContractDeploy <a href="#txtypesmartcontractdeploy" id="txtypesmartcontractdeploy"></a>

TxTypeSmartContractDeploy deploys a smart contract to the given address. The following changes will be made by this transaction type.

1. The sender's balance decreases by the amount of the transaction fee.
2. The sender's nonce increases by one.
3. `input`에 기입된 코드로 스마트 컨트랙트가 배포됩니다. 배포된 주소는 영수증의 `contractAddress`를 통해 반환됩니다.
4. `value` KLAY is transferred from the sender to the recipient.

### Attributes <a href="#attributes" id="attributes"></a>

| Attribute     | Type                                      | Description                                                                                                                                                                                                                                                                                                                                        |
| ------------- | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| type          | uint8 (Go)                                | TxTypeSmartContractDeploy의 유형입니다. 이는 0x28이어야 합니다.                                                                                                                                                                                                                                                                                                  |
| nonce         | uint64 (Go)                               | A value used to uniquely identify a sender’s transaction. If two transactions with the same nonce are generated by a sender, only one is executed.                                                                                                                                                                                                 |
| gasPrice      | \*big.Int (Go)                            | A unit price of gas in `peb` the sender will pay for a transaction fee. The amount of transaction fee is calculated as `gas` \* `gasPrice`. For example, if the transaction consumes 10 units of gas and gasPrice is 10^18, the transaction fee will be 10 KLAY. See [Unit of KLAY](/content/klaytn/design/klaytn-native-coin-klay#units-of-klay). |
| gas           | uint64 (Go)                               | The maximum amount of gas the transaction is allowed to use.                                                                                                                                                                                                                                                                                       |
| to            | \*common.Address (Go)                     | The account address that will receive the transferred value. 현재 이 값은 nil이어야합니다. Specifying the address will be supported in the future.                                                                                                                                                                                                            |
| value         | \*big.Int (Go)                            | The amount of KLAY in `peb` to be transferred.                                                                                                                                                                                                                                                                                                     |
| from          | common.Address (Go)                       | The address of the sender. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                 |
| input         | \[]byte (Go)                              | Data attached to the transaction, used for transaction execution.                                                                                                                                                                                                                                                                                  |
| humanReadable | bool (Go)                                 | Human-readable address는 아직 지원되지 않으므로 이 값은 false여야 합니다. 이 값이 true라면 트랜잭션은 실패합니다.                                                                                                                                                                                                                                                                    |
| codeFormat    | uint8 (Go)                                | The code format of smart contract code. 현재는 오직 EVM(0x00)만 지원됩니다.                                                                                                                                                                                                                                                                                   |
| txSignatures  | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The sender's signatures. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                   |

### RLP Encoding for Signature <a href="#rlp-encoding-for-signature" id="rlp-encoding-for-signature"></a>

To make a signature of this transaction type, RLP serialization should be done like the following:

```javascript
SigRLP = encode([encode([type, nonce, gasPrice, gas, to, value, from, input, humanReadable, codeFormat]), chainid, 0, 0])
SigHash = keccak256(SigRLP)
Signature = sign(SigHash, <private key>)
```

### RLP Encoding for SenderTxHash <a href="#rlp-encoding-for-sendertxhash" id="rlp-encoding-for-sendertxhash"></a>

To make a SenderTxHash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
SenderTxHashRLP = type + encode([nonce, gasPrice, gas, to, value, from, input, humanReadable, codeFormat, txSignatures])
SenderTxHash = keccak256(SenderTxHashRLP)
```

### RLP Encoding for Transaction Hash <a href="#rlp-encoding-for-transaction-hash" id="rlp-encoding-for-transaction-hash"></a>

수수료 납부자의 서명을 만들려면 RLP 직렬화를 다음과 같이 수행해야합니다.

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
TxHashRLP = type + encode([nonce, gasPrice, gas, to, value, from, input, humanReadable, codeFormat, txSignatures])
TxHash = keccak256(TxHashRLP)
```

### RLP Encoding (Example) <a href="#rlp-encoding-example" id="rlp-encoding-example"></a>

The following shows the result of RLP serialization and the transaction object:

```javascript
ChainID 0x1
PrivateKey 0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8
PublicKey.X 0x3a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d
PublicKey.Y 0x8072e77939dc03ba44790779b7a1025baf3003f6732430e20cd9b76d953391b3
SigRLP 0xf90240b9023af90237288204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0bb901fe608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f00290180018080
SigHash 0xa921fa892d5dec0837bd32c1fb77fc3b2df57ec0b0c4eea79192c79883ed543c
Signature f845f84325a0fcd107738fb47750ba727610aefd6d5f51ac8163d62ce500e7ab7e15defe7088a0383d68220d0266490ea4173c1d7847f22fcbe22f8c8125e1c0589189845c902a
TxHashRLP 0x28f9027d8204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0bb901fe608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f00290180f845f84325a0fcd107738fb47750ba727610aefd6d5f51ac8163d62ce500e7ab7e15defe7088a0383d68220d0266490ea4173c1d7847f22fcbe22f8c8125e1c0589189845c902a
TxHash e983f38b814891990f3ca57028c2230dc7e907eb313c827e7c99fadcc9b4c58b
SenderTxHashRLP 0x28f9027d8204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0bb901fe608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f00290180f845f84325a0fcd107738fb47750ba727610aefd6d5f51ac8163d62ce500e7ab7e15defe7088a0383d68220d0266490ea4173c1d7847f22fcbe22f8c8125e1c0589189845c902a
SenderTxHash e983f38b814891990f3ca57028c2230dc7e907eb313c827e7c99fadcc9b4c58b

    TX(e983f38b814891990f3ca57028c2230dc7e907eb313c827e7c99fadcc9b4c58b)
    Type:          TxTypeSmartContractDeploy
    From:          0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B
    To:            0x7b65B75d204aBed71587c9E519a89277766EE1d0
    Nonce:         1234
    GasPrice:      0x19
    GasLimit:      0xf4240
    Value:         0xa
    Signature:     [{"V":"0x25","R":"0xfcd107738fb47750ba727610aefd6d5f51ac8163d62ce500e7ab7e15defe7088","S":"0x383d68220d0266490ea4173c1d7847f22fcbe22f8c8125e1c0589189845c902a"}]
    Data:          363038303630343035323334383031353631303031303537363030303830666435623530363130316465383036313030323036303030333936303030663330303630383036303430353236303034333631303631303036313537363366666666666666663763303130303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303630303033353034313636333161333964386566383131343631303038303537383036333633353335383662313436313030613735373830363337306130383233313134363130306361353738303633666436623765663831343631303066383537356233333630303039303831353236303031363032303532363034303831323038303534333439303831303139303931353538313534303139303535303035623334383031353631303038633537363030303830666435623530363130303935363130313064353635623630343038303531393138323532353139303831393030333630323030313930663335623631303063383733666666666666666666666666666666666666666666666666666666666666666666666666666666663630303433353136363130313133353635623030356233343830313536313030643635373630303038306664356235303631303039353733666666666666666666666666666666666666666666666666666666666666666666666666666666663630303433353136363130313437353635623334383031353631303130343537363030303830666435623530363130306338363130313539353635623630303035343831353635623733666666666666666666666666666666666666666666666666666666666666666666666666666666663136363030303930383135323630303136303230353236303430383132303830353433343930383130313930393135353831353430313930353535363562363030313630323035323630303039303831353236303430393032303534383135363562333336303030393038313532363030313630323035323630343038313230383035343930383239303535393038313131313536313031616635373630343035313333393038323135363130386663303239303833393036303030383138313831383538383838663139333530353035303530313536313031396335373631303161663536356233333630303039303831353236303031363032303532363034303930323038313930353535623530353630306131363536323761376137323330353832303632376361343662623039343738613031353736323830366363303063343331323330353031313138633763323663333061633538633465303965353163346630303239
    HumanReadable: true
    CodeFormat:    CodeFormatEVM
    Hex:           28f9027d8204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0bb901fe608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f00290180f845f84325a0fcd107738fb47750ba727610aefd6d5f51ac8163d62ce500e7ab7e15defe7088a0383d68220d0266490ea4173c1d7847f22fcbe22f8c8125e1c0589189845c902a
```

### RPC Output (Example) <a href="#rpc-output-example" id="rpc-output-example"></a>

The following shows a transaction object returned via JSON RPC.

```javascript
{
  "blockHash": "0x82983fe294d286e76486760e6904369285554e1744af16786c2393a956fb4ec4",
  "blockNumber": "0x2",
  "codeFormat": "0x0",
  "contractAddress": "0x636f6e74726163742e6b6c6179746e0000000000",
  "from": "0x0fcda0f2efbe1b4e61b487701ce4f2f8abc3723d",
  "gas": "0x174876e800",
  "gasPrice": "0x0",
  "gasUsed": "0xee6e343d",
  "humanReadable": true,
  "input": "0x608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f0029",
  "logs": [],
  "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "nonce": "0xa",
  "senderTxHash": "0x78a5633ee5b453ed2f00937e65945a3b76e96623634e1555e2f15d44930168af",
  "signatures": [
    {
      "V": "0x25",
      "R": "0x369d892dc24786111fd8f0308e8a6518708727257e95b3281865508faa0a768b",
      "S": "0x12fc22c390a89484d1cb70e1f19c4fa8a203b1406044ee9c263264876f0dd724"
    }
  ],
  "status": "0x1",
  "to": "0x636f6e74726163742e6b6c6179746e0000000000",
  "transactionHash": "0x78a5633ee5b453ed2f00937e65945a3b76e96623634e1555e2f15d44930168af",
  "transactionIndex": "0x3",
  "type": "TxTypeSmartContractDeploy",
  "typeInt": 40,
  "value": "0x0"
}
```

## TxTypeSmartContractExecution <a href="#txtypesmartcontractexecution" id="txtypesmartcontractexecution"></a>

TxTypeSmartContractExecution executes a smart contract with the given data in `input`. TxTypeSmartContractExecution는 `to`가 스마트 컨트랙트 계정일 때만 실행됩니다. KLAY를 외부 소유 계정으로 전송하려면 [TxTypeValueTransfer](#txtypevaluetransfer)를 대신 사용하십시오. The following changes will be made by this transaction type.

1. `to`가 스마트 컨트랙트라면 `input`을 이용하여 코드가 실행됩니다. 그렇지 않으면 트랜잭션은 거절됩니다.
2. The sender's balance decreases by the amount of the transaction fee.
3. The sender's nonce increases by one.
4. `value`에 값이 입력되었으면 발신자에서 `to`로`value` KLAY가 전송됩니다. 컨트랙트가 KLAY를 받기 위해서는 컨트랙트는 payable fallback function을 가져야 합니다.

### Attributes <a href="#attributes" id="attributes"></a>

| Attribute    | Type                                      | Description                                                                                                                                                                                                                                                                                                                                        |
| ------------ | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| type         | uint8 (Go)                                | TxTypeSmartContractExecution의 유형입니다. 이는 0x30이어야 합니다.                                                                                                                                                                                                                                                                                               |
| nonce        | uint64 (Go)                               | A value used to uniquely identify a sender’s transaction. If two transactions with the same nonce are generated by a sender, only one is executed.                                                                                                                                                                                                 |
| gasPrice     | \*big.Int (Go)                            | A unit price of gas in `peb` the sender will pay for a transaction fee. The amount of transaction fee is calculated as `gas` \* `gasPrice`. For example, if the transaction consumes 10 units of gas and gasPrice is 10^18, the transaction fee will be 10 KLAY. See [Unit of KLAY](/content/klaytn/design/klaytn-native-coin-klay#units-of-klay). |
| gas          | uint64 (Go)                               | The maximum amount of gas the transaction is allowed to use.                                                                                                                                                                                                                                                                                       |
| to           | common.Address (Go)                       | The address of the smart contract account to be executed.                                                                                                                                                                                                                                                                                          |
| value        | \*big.Int (Go)                            | The amount of KLAY in `peb` to be transferred.                                                                                                                                                                                                                                                                                                     |
| from         | common.Address (Go)                       | The address of the sender. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                 |
| input        | \[]byte (Go)                              | Data attached to the transaction, used for transaction execution.                                                                                                                                                                                                                                                                                  |
| txSignatures | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The sender's signatures. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                   |

### RLP Encoding for Signature <a href="#rlp-encoding-for-signature" id="rlp-encoding-for-signature"></a>

To make a signature of this transaction type, RLP serialization should be done like the following:

```javascript
SigRLP = encode([encode([type, nonce, gasPrice, gas, to, value, from, input]), chainid, 0, 0])
SigHash = keccak256(SigRLP)
Signature = sign(SigHash, <private key>)
```

### RLP Encoding for SenderTxHash <a href="#rlp-encoding-for-sendertxhash" id="rlp-encoding-for-sendertxhash"></a>

To make a SenderTxHash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
SenderTxHashRLP = type + encode([nonce, gasPrice, gas, to, value, from, input, txSignatures])
SenderTxHash = keccak256(SenderTxHashRLP)
```

### RLP Encoding for Transaction Hash <a href="#rlp-encoding-for-transaction-hash" id="rlp-encoding-for-transaction-hash"></a>

To make a transaction hash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
TxHashRLP = type + encode([nonce, gasPrice, gas, to, value, from, input, txSignatures])
TxHash = keccak256(TxHashRLP)
```

### RLP Encoding (Example) <a href="#rlp-encoding-example" id="rlp-encoding-example"></a>

The following shows the result of RLP serialization and the transaction object:

```javascript
ChainID 0x1
PrivateKey 0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8
PublicKey.X 0x3a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d
PublicKey.Y 0x8072e77939dc03ba44790779b7a1025baf3003f6732430e20cd9b76d953391b3
SigRLP 0xf860b85bf859308204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0ba46353586b000000000000000000000000bc5951f055a85f41a3b62fd6f68ab7de76d299b2018080
SigHash 0x197ea7d262f74489934d6cbcf8baa3bec169c16ad672fef4a9f8148864c9cdce
Signature f845f84326a0e4276df1a779274fbb04bc18a0184809eec1ce9770527cebb3d64f926dc1810ba04103b828a0671a48d64fe1a3879eae229699f05a684d9c5fd939015dcdd9709b
TxHashRLP 0x30f89f8204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0ba46353586b000000000000000000000000bc5951f055a85f41a3b62fd6f68ab7de76d299b2f845f84326a0e4276df1a779274fbb04bc18a0184809eec1ce9770527cebb3d64f926dc1810ba04103b828a0671a48d64fe1a3879eae229699f05a684d9c5fd939015dcdd9709b
TxHash 23bb192bd58d56527843eb63225c5213f3aded95e4c9776f1ff0bdd8ee0b6826
SenderTxHashRLP 0x30f89f8204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0ba46353586b000000000000000000000000bc5951f055a85f41a3b62fd6f68ab7de76d299b2f845f84326a0e4276df1a779274fbb04bc18a0184809eec1ce9770527cebb3d64f926dc1810ba04103b828a0671a48d64fe1a3879eae229699f05a684d9c5fd939015dcdd9709b
SenderTxHash 23bb192bd58d56527843eb63225c5213f3aded95e4c9776f1ff0bdd8ee0b6826

    TX(23bb192bd58d56527843eb63225c5213f3aded95e4c9776f1ff0bdd8ee0b6826)
    Type:          TxTypeSmartContractExecution
    From:          0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B
    To:            0x7b65B75d204aBed71587c9E519a89277766EE1d0
    Nonce:         1234
    GasPrice:      0x19
    GasLimit:      0xf4240
    Value:         0xa
    Signature:     [{"V":"0x26","R":"0xe4276df1a779274fbb04bc18a0184809eec1ce9770527cebb3d64f926dc1810b","S":"0x4103b828a0671a48d64fe1a3879eae229699f05a684d9c5fd939015dcdd9709b"}]
    Data:          363335333538366230303030303030303030303030303030303030303030303062633539353166303535613835663431613362363266643666363861623764653736643239396232
    Hex:           30f89f8204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0ba46353586b000000000000000000000000bc5951f055a85f41a3b62fd6f68ab7de76d299b2f845f84326a0e4276df1a779274fbb04bc18a0184809eec1ce9770527cebb3d64f926dc1810ba04103b828a0671a48d64fe1a3879eae229699f05a684d9c5fd939015dcdd9709b
```

### RPC Output (Example) <a href="#rpc-output-example" id="rpc-output-example"></a>

The following shows a transaction object returned via JSON RPC.

```javascript
{
  "blockHash": "0x82983fe294d286e76486760e6904369285554e1744af16786c2393a956fb4ec4",
  "blockNumber": "0x2",
  "contractAddress": null,
  "from": "0x0fcda0f2efbe1b4e61b487701ce4f2f8abc3723d",
  "gas": "0x174876e800",
  "gasPrice": "0x5d21dba00",
  "gasUsed": "0xfedc",
  "input": "0x6353586b0000000000000000000000000fcda0f2efbe1b4e61b487701ce4f2f8abc3723d",
  "logs": [],
  "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "nonce": "0xd",
  "senderTxHash": "0xe216873dedd72d8d67a9f5e51eb5a7ed2b5f34bca334adff7a3601d6d3e2e132",
  "signatures": [
    {
      "V": "0x26",
      "R": "0x68fe3dfd1ff3ea14427f157b5837cb6eb0b00fd0497e1c80897de1935200f0",
      "S": "0x6b84fbedcb4ff785120890596fad3f797c178cda8908f3b02ee0a4442fbf4189"
    }
  ],
  "status": "0x1",
  "to": "0x636f6e74726163742e6b6c6179746e0000000000",
  "transactionHash": "0xe216873dedd72d8d67a9f5e51eb5a7ed2b5f34bca334adff7a3601d6d3e2e132",
  "transactionIndex": "0x6",
  "type": "TxTypeSmartContractExecution",
  "typeInt": 48,
  "value": "0xa"
}
```

## TxTypeAccountUpdate <a href="#txtypeaccountupdate" id="txtypeaccountupdate"></a>

TxTypeAccountUpdate updates the key of the given account. 이 트랜잭션 유형은 다음과 같은 변경 사항을 만듭니다.

1. The sender's balance decreases by the amount of the transaction fee.
2. The sender's nonce increases by one.
3. 계정의 키는 `key`로 업데이트됩니다.
4. 이 유형의 트랜잭션이 실행되고 나면 계정에서 전송된 트랜잭션은 새 `key`로 검증됩니다.

### Attributes <a href="#attributes" id="attributes"></a>

| Attribute    | Type                                      | Description                                                                                                                                                                                                                                                                                                                      |
| ------------ | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| type         | uint8 (Go)                                | TxTypeAccountUpdate의 유형입니다. 이는 0x20이어야 합니다.                                                                                                                                                                                                                                                                                      |
| nonce        | uint64 (Go)                               | A value used to uniquely identify a sender’s transaction. If two transactions with the same nonce are generated by a sender, only one is executed.                                                                                                                                                                               |
| gasPrice     | \*big.Int (Go)                            | A multiplier to get how much the sender will pay in tokens. The amount of tokens the sender will pay is calculated via `gas` \* `gasPrice`. For example, the sender will pay 10 KLAY for a transaction fee if gas is 10 and gasPrice is 10^18. See [Unit of KLAY](/content/klaytn/design/klaytn-native-coin-klay#units-of-klay). |
| gas          | uint64 (Go)                               | The maximum amount of transaction fee the transaction is allowed to use.                                                                                                                                                                                                                                                         |
| from         | common.Address (Go)                       | The address of the sender. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                               |
| key          | AccountKey (Go)                           | [AccountKey](/content/klaytn/design/accounts#account-key) to be updated to the account.                                                                                                                                                                                                                                          |
| txSignatures | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The sender's signatures. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                 |

### RLP Encoding for Signature <a href="#rlp-encoding-for-signature" id="rlp-encoding-for-signature"></a>

To make a signature of this transaction type, RLP serialization should be done like the following:

```javascript
SigRLP = encode([encode([type, nonce, gasPrice, gas, from, rlpEncodedKey]), chainid, 0, 0])
SigHash = keccak256(SigRLP)
Signature = sign(SigHash, <private key>)
```

### RLP Encoding for SenderTxHash <a href="#rlp-encoding-for-sendertxhash" id="rlp-encoding-for-sendertxhash"></a>

To make a SenderTxHash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
SenderTxHashRLP = type + encode([nonce, gasPrice, gas, from, rlpEncodedKey, txSignatures])
SenderTxHash = keccak256(SenderTxHashRLP)
```

### RLP Encoding for Transaction Hash <a href="#rlp-encoding-for-transaction-hash" id="rlp-encoding-for-transaction-hash"></a>

To make a transaction hash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
TxHashRLP = type + encode([nonce, gasPrice, gas, from, rlpEncodedKey, txSignatures])
TxHash = keccak256(TxHashRLP)
```

### RLP Encoding (Example) <a href="#rlp-encoding-example" id="rlp-encoding-example"></a>

The following shows the result of RLP serialization and the transaction object:

```javascript
ChainID 0x1
PrivateKey 0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8
PublicKey.X 0x3a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d
PublicKey.Y 0x8072e77939dc03ba44790779b7a1025baf3003f6732430e20cd9b76d953391b3
SigRLP 0xf849b844f842208204d219830f424094a94f5374fce5edbc8e2a8697c15331677e6ebf0ba302a1033a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d018080
SigHash 0xa0d3f1d2b4f061c3a5d9c22c7bb621aa821162b42b4db6cf1888defc2473e0ab
Signature f845f84325a0f7d479628f05f51320f0842193e3f7ae55a5b49d3645bf55c35bee1e8fd2593aa04de8eab5338fdc86e96f8c49ed516550f793fc2c4007614ce3d2a6b33cf9e451
TxHashRLP 0x20f8888204d219830f424094a94f5374fce5edbc8e2a8697c15331677e6ebf0ba302a1033a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33df845f84325a0f7d479628f05f51320f0842193e3f7ae55a5b49d3645bf55c35bee1e8fd2593aa04de8eab5338fdc86e96f8c49ed516550f793fc2c4007614ce3d2a6b33cf9e451
TxHash 8c70627d6b637c7d033ead083fc5e43e5cad10c704a86dd9bda7ac104a0e5ad0
SenderTxHashRLP 0x20f8888204d219830f424094a94f5374fce5edbc8e2a8697c15331677e6ebf0ba302a1033a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33df845f84325a0f7d479628f05f51320f0842193e3f7ae55a5b49d3645bf55c35bee1e8fd2593aa04de8eab5338fdc86e96f8c49ed516550f793fc2c4007614ce3d2a6b33cf9e451
SenderTxHash 8c70627d6b637c7d033ead083fc5e43e5cad10c704a86dd9bda7ac104a0e5ad0

    TX(8c70627d6b637c7d033ead083fc5e43e5cad10c704a86dd9bda7ac104a0e5ad0)
    Type:          TxTypeAccountUpdate
    From:          0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B
    Nonce:         1234
    GasPrice:      0x19
    GasLimit:      0xf4240
    Key:           AccountKeyPublic: S256Pubkey:{"x":"0x3a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d","y":"0x8072e77939dc03ba44790779b7a1025baf3003f6732430e20cd9b76d953391b3"}
    Signature:     [{"V":"0x25","R":"0xf7d479628f05f51320f0842193e3f7ae55a5b49d3645bf55c35bee1e8fd2593a","S":"0x4de8eab5338fdc86e96f8c49ed516550f793fc2c4007614ce3d2a6b33cf9e451"}]
    Hex:           20f8888204d219830f424094a94f5374fce5edbc8e2a8697c15331677e6ebf0ba302a1033a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33df845f84325a0f7d479628f05f51320f0842193e3f7ae55a5b49d3645bf55c35bee1e8fd2593aa04de8eab5338fdc86e96f8c49ed516550f793fc2c4007614ce3d2a6b33cf9e451
```

### RPC Output (Example) <a href="#rpc-output-example" id="rpc-output-example"></a>

The following shows a transaction object returned via JSON RPC.

```javascript
{
  "blockHash": "0x82983fe294d286e76486760e6904369285554e1744af16786c2393a956fb4ec4",
  "blockNumber": "0x2",
  "contractAddress": null,
  "from": "0x636f6c696e2e6b6c6179746e0000000000000000",
  "gas": "0x174876e800",
  "gasPrice": "0x5d21dba00",
  "gasUsed": "0xa028",
  "key": "0x02a1034ef27ba4b7d1ae09b166744c5b7ee4a7a0cc5c76b2e5d74523a0a4fb56db3191",
  "logs": [],
  "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "nonce": "0x0",
  "senderTxHash": "0x3f154903f92a179007b45b807af2d971ada9a23657e80bf5c18a75ac6516fd0b",
  "signatures": [
    {
      "V": "0x25",
      "R": "0x757827ec43eafdc150ecb35423699ceaea41b13dd07f8620e2231a7b0e278149",
      "S": "0x59d43ed3e0ed0f9d69d0c08ccca29913a8b138c000029f878f61337220a1ca1b"
    }
  ],
  "status": "0x1",
  "transactionHash": "0x3f154903f92a179007b45b807af2d971ada9a23657e80bf5c18a75ac6516fd0b",
  "transactionIndex": "0x0",
  "type": "TxTypeAccountUpdate",
  "typeInt": 32
}
```

## TxTypeCancel <a href="#txtypecancel" id="txtypecancel"></a>

TxTypeCancel cancels the execution of the transaction with the same nonce in the transaction pool. 이 트랜잭션 유형은 제출된 트랜잭션이 일정 시간 동안 처리되지 않은 것으로 보일 때 유용합니다. 트랜잭션이 처리되지 않은 것처럼 보이는 경우가 몇 가지 있습니다: 1. 트랜잭션이 어딘가에서 손실되어 컨센서스 노드에 도달하지 못하는 경우 2. 어떤 컨센서스 노드에서도 아직 트랜잭션이 처리되지 않은 경우 3. 트랜잭션이 처리되었지만 트랜잭션이 포함된 블록이 전달되지 않은 경우

클라이언트 쪽에서는 정확한 원인을 파악하기가 매우 어렵습니다. 이유를 파악하려면 모든 컨센서스 노드를 살펴봐야 합니다. 단, 일반 사람들이 컨센서스 노드에 연결하는 것은 금지됩니다. 이러한 상황에서 일반적인 블록체인 플랫폼에서는 사용자가 이전 트랜잭션을 대체하기 위해 다른 트랜잭션을 더 높은 가스 가격으로 제출하는 경우가 많습니다. 다만, Klaytn에서는 가스 가격이 고정돼 있기 때문에, 기존 트랜잭션을 더 높은 가스 가격으로 대체하는 것은 불가능합니다.

트랜잭션이 처리되지 않은 상태로 유지되는 경우, 더 높은 논스를 가진 다른 트랜잭션이 처리될 수 없습니다. 논스로 트랜잭션 실행 순서가 결정되기 때문입니다.

이 문제를 해결하기 위해 Klaytn은 트랜잭션 유형 TxTypeCancel을 제공합니다. 사용자는 이러한 상황에 직면하면 TxTypeCancel 트랜잭션을 전송할 수 있습니다.

위의 각 상황은 다음과 같이 처리됩니다. 1. 이전 트랜잭션이 손실된 경우 TxTypeCancel 트랜잭션이 실행되어 블록에 포함됩니다. 2. 이전 트랜잭션이 아직 처리되지 않은 경우 TxTypeCancel은 이전 트랜잭션을 대체합니다. 그런 다음 실행되어 블록에 포함됩니다. 3. 이전 트랜잭션이 이미 실행된 경우, 논스가 증가했으므로 TxTypeCancel 트랜잭션은 논스가 낮아서 삭제됩니다.

TxTypeCancel 트랜잭션은 동일한 논스의 트랜잭션을 대체 할 수 있는 유일한 트랜잭션입니다. 다른 트랜잭션 유형은동일한 논스의 트랜잭션으로 바꿀 수 없습니다.

이 트랜잭션 유형은 다음과 같은 변경 사항을 만듭니다. 1. The sender's balance decreases by the amount of the transaction fee. 2. The sender's nonce increases by one.

### Attributes <a href="#attributes" id="attributes"></a>

| Attribute    | Type                                      | Description                                                                                                                                                                                                                                                                                                                                        |
| ------------ | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| type         | uint8 (Go)                                | TxTypeCancel의 유형입니다. 이는 0x38이어야 합니다.                                                                                                                                                                                                                                                                                                               |
| nonce        | uint64 (Go)                               | A value used to uniquely identify a sender’s transaction. If two transactions with the same nonce are generated by a sender, only one is executed. `TxTypeCancel`을 사용할 때 이 값은 취소할 타겟 트랜잭션의 논스 값과 같아야 합니다.                                                                                                                                          |
| gasPrice     | \*big.Int (Go)                            | A unit price of gas in `peb` the sender will pay for a transaction fee. The amount of transaction fee is calculated as `gas` \* `gasPrice`. For example, if the transaction consumes 10 units of gas and gasPrice is 10^18, the transaction fee will be 10 KLAY. See [Unit of KLAY](/content/klaytn/design/klaytn-native-coin-klay#units-of-klay). |
| gas          | uint64 (Go)                               | The maximum amount of transaction fee the transaction is allowed to use.                                                                                                                                                                                                                                                                           |
| from         | common.Address (Go)                       | The address of the sender. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                 |
| txSignatures | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The sender's signatures. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                   |

결과:

1. 같은 논스를 가진 트랜잭션이 있으면, 이 취소 트랜잭션으로 대체됩니다.
2. 만약 같은 논스가 없으면 이 트랜잭션은 보통 트랜잭션으로 삽입됩니다.
3. 취소 트랜잭션은 다른 트랜잭션 유형으로 대체되지 않습니다.

### RLP Encoding for Signature <a href="#rlp-encoding-for-signature" id="rlp-encoding-for-signature"></a>

To make a transaction signature, RLP serialization should be done like the following:

```javascript
SigRLP = encode([encode([type, nonce, gasPrice, gas, from]), chainid, 0, 0])
SigHash = keccak256(SigRLP)
Signature = sign(SigHash, <private key>)
```

### RLP Encoding for SenderTxHash <a href="#rlp-encoding-for-sendertxhash" id="rlp-encoding-for-sendertxhash"></a>

To make a SenderTxHash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
SenderTxHashRLP = type + encode([nonce, gasPrice, gas, from, txSignatures])
SenderTxHash = keccak256(SenderTxHashRLP)
```

### RLP Encoding for Transaction Hash <a href="#rlp-encoding-for-transaction-hash" id="rlp-encoding-for-transaction-hash"></a>

To make a transaction hash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
TxHashRLP = type + encode([nonce, gasPrice, gas, from, txSignatures])
TxHash = keccak256(TxHashRLP)
```

### RLP Encoding (Example) <a href="#rlp-encoding-example" id="rlp-encoding-example"></a>

The following shows the result of RLP serialization and the transaction object:

```javascript
ChainID 0x1
PrivateKey 0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8
PublicKey.X 0x3a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d
PublicKey.Y 0x8072e77939dc03ba44790779b7a1025baf3003f6732430e20cd9b76d953391b3
SigRLP 0xe39fde388204d219830f424094a94f5374fce5edbc8e2a8697c15331677e6ebf0b018080
SigHash 0xaaac6d71ad921e8a12e92c47d0b0654a20d8d9a4ff70d83f78661ccdf062ce9a
Signature f845f84325a0fb2c3d53d2f6b7bb1deb5a09f80366a5a45429cc1e3956687b075a9dcad20434a05c6187822ee23b1001e9613d29a5d6002f990498d2902904f7f259ab3358216e
TxHashRLP 0x38f8648204d219830f424094a94f5374fce5edbc8e2a8697c15331677e6ebf0bf845f84325a0fb2c3d53d2f6b7bb1deb5a09f80366a5a45429cc1e3956687b075a9dcad20434a05c6187822ee23b1001e9613d29a5d6002f990498d2902904f7f259ab3358216e
TxHash 10d135d590cb587cc45c1f94f4a0e3b8c24d24a6e4243f09ca395fb4e2450413
SenderTxHashRLP 0x38f8648204d219830f424094a94f5374fce5edbc8e2a8697c15331677e6ebf0bf845f84325a0fb2c3d53d2f6b7bb1deb5a09f80366a5a45429cc1e3956687b075a9dcad20434a05c6187822ee23b1001e9613d29a5d6002f990498d2902904f7f259ab3358216e
SenderTxHash 10d135d590cb587cc45c1f94f4a0e3b8c24d24a6e4243f09ca395fb4e2450413

    TX(10d135d590cb587cc45c1f94f4a0e3b8c24d24a6e4243f09ca395fb4e2450413)
    Type:          TxTypeCancel
    From:          0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B
    Nonce:         1234
    GasPrice:      0x19
    GasLimit:      0xf4240
    Signature:     [{"V":"0x25","R":"0xfb2c3d53d2f6b7bb1deb5a09f80366a5a45429cc1e3956687b075a9dcad20434","S":"0x5c6187822ee23b1001e9613d29a5d6002f990498d2902904f7f259ab3358216e"}]
    Hex:           38f8648204d219830f424094a94f5374fce5edbc8e2a8697c15331677e6ebf0bf845f84325a0fb2c3d53d2f6b7bb1deb5a09f80366a5a45429cc1e3956687b075a9dcad20434a05c6187822ee23b1001e9613d29a5d6002f990498d2902904f7f259ab3358216e
```

### RPC Output (Example) <a href="#rpc-output-example" id="rpc-output-example"></a>

The following shows a transaction object returned via JSON RPC.

```javascript
{
  "blockHash": "0x82983fe294d286e76486760e6904369285554e1744af16786c2393a956fb4ec4",
  "blockNumber": "0x2",
  "contractAddress": null,
  "from": "0x0fcda0f2efbe1b4e61b487701ce4f2f8abc3723d",
  "gas": "0x174876e800",
  "gasPrice": "0x5d21dba00",
  "gasUsed": "0x5208",
  "logs": [],
  "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "nonce": "0x10",
  "senderTxHash": "0x0370adf89b2463d3d1fd894d6328929c931ef0cc3a8f1481affedd2e9c88d9d6",
  "signatures": [
    {
      "V": "0x26",
      "R": "0xad73f30acfb80090cba8d3f4be4696e65f8eb7c36b85aac06a9bea350d10578f",
      "S": "0x7ec2d6f052d8f916d12db2e0310381201888cb12d3a3696da80cab5195833706"
    }
  ],
  "status": "0x1",
  "transactionHash": "0x0370adf89b2463d3d1fd894d6328929c931ef0cc3a8f1481affedd2e9c88d9d6",
  "transactionIndex": "0x9",
  "type": "TxTypeCancel",
  "typeInt": 56
}
```

## TxTypeChainDataAnchoring <a href="#txtypechaindataanchoring" id="txtypechaindataanchoring"></a>

TxTypeChainDataAnchoringTransaction는 서비스체인 데이터를 Klaytn 메인체인에 앵커링하는 트랜잭션입니다. 서비스체인은 주기적으로 이러한 종류의 트랜잭션을 Klaytn 메인체인에 보내어 자신의 데이터 보안과 신뢰성을 검증받습니다. 데이터 앵커링에 관한 더 자세한 내용은 [Anchoring](https://github.com/klaytn/klaytn-docs-ko/blob/main/docs/node/service-chain/references/anchoring.md)을 참조하시기 바랍니다. 이 트랜잭션은 RPC 호출로 전송하시면 안 된다는 점을 유의하시기 바랍니다. 현재 이 트랜잭션은 보안상의 이유로 비공개 p2p 채널을 통해 실행됩니다. 이 트랜잭션은 발신자의 논스를 1씩 증가시키는 것을 제외하고는 Klaytn 블록 체인의 상태를 변경하지 않습니다.

### Attributes <a href="#attributes" id="attributes"></a>

| Attribute    | Type                                      | Description                                                                                                                                                                                                                                                                                                                                        |
| ------------ | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| type         | uint8 (Go)                                | TxTypeChainDataAnchoringTransaction의 유형입니다. 이는 0x48이어야 합니다.                                                                                                                                                                                                                                                                                        |
| nonce        | uint64 (Go)                               | A value used to uniquely identify a sender’s transaction. If two transactions with the same nonce are generated by a sender, only one is executed.                                                                                                                                                                                                 |
| gasPrice     | \*big.Int (Go)                            | A unit price of gas in `peb` the sender will pay for a transaction fee. The amount of transaction fee is calculated as `gas` \* `gasPrice`. For example, if the transaction consumes 10 units of gas and gasPrice is 10^18, the transaction fee will be 10 KLAY. See [Unit of KLAY](/content/klaytn/design/klaytn-native-coin-klay#units-of-klay). |
| gas          | uint64 (Go)                               | The maximum amount of transaction fee the transaction is allowed to use.                                                                                                                                                                                                                                                                           |
| from         | common.Address (Go)                       | The address of the sender. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                 |
| input        | \[]byte (Go)                              | Data of the service chain.                                                                                                                                                                                                                                                                                                                         |
| txSignatures | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The sender's signatures. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                   |

### RLP Encoding for Signature <a href="#rlp-encoding-for-signature" id="rlp-encoding-for-signature"></a>

To make a signature of this transaction type, RLP serialization should be done like the following:

```javascript
SigRLP = encode([encode([type, nonce, gasPrice, gas, from, anchoredData]), chainid, 0, 0])
SigHash = keccak256(SigRLP)
Signature = sign(SigHash, <private key>)
```

### RLP Encoding for SenderTxHash <a href="#rlp-encoding-for-sendertxhash" id="rlp-encoding-for-sendertxhash"></a>

To make a SenderTxHash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
SenderTxHashRLP = type + encode([nonce, gasPrice, gas, from, anchoredData, txSignatures])
SenderTxHash = keccak256(SenderTxHashRLP)
```

### RLP Encoding for Transaction Hash <a href="#rlp-encoding-for-transaction-hash" id="rlp-encoding-for-transaction-hash"></a>

To make a transaction hash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
TxHashRLP = type + encode([nonce, gasPrice, gas, from, anchoredData, txSignatures])
TxHash = keccak256(TxHashRLP)
```

### RLP Encoding (Example) <a href="#rlp-encoding-example" id="rlp-encoding-example"></a>

The following shows the result of RLP serialization and the transaction object:

```javascript
ChainID 0x1
PrivateKey 0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8
PublicKey.X 0x3a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d
PublicKey.Y 0x8072e77939dc03ba44790779b7a1025baf3003f6732430e20cd9b76d953391b3
SigRLP 0xf8cfb8caf8c8488204d219830f424094a94f5374fce5edbc8e2a8697c15331677e6ebf0bb8a8f8a6a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000405018080
SigHash 0x07e07c69a12e384c16d94157c99d0a6fbae1d99f5d54501bfdc5937bbee7c792
Signature f845f84325a0e58b9abf9f33a066b998fccaca711553fb4df425c9234bbb3577f9d9775bb124a02c409a6c5d92277c0a812dd0cc553d7fe1d652a807274c3786df3292cd473e09
TxHashRLP 0x48f9010e8204d219830f424094a94f5374fce5edbc8e2a8697c15331677e6ebf0bb8a8f8a6a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000405f845f84325a0e58b9abf9f33a066b998fccaca711553fb4df425c9234bbb3577f9d9775bb124a02c409a6c5d92277c0a812dd0cc553d7fe1d652a807274c3786df3292cd473e09
TxHash 4aad85735e777795d24aa3eab51be959d8ebdf9683083d85b66f70b7170f2ea3
SenderTxHashRLP 0x48f9010e8204d219830f424094a94f5374fce5edbc8e2a8697c15331677e6ebf0bb8a8f8a6a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000405f845f84325a0e58b9abf9f33a066b998fccaca711553fb4df425c9234bbb3577f9d9775bb124a02c409a6c5d92277c0a812dd0cc553d7fe1d652a807274c3786df3292cd473e09
SenderTxHash 4aad85735e777795d24aa3eab51be959d8ebdf9683083d85b66f70b7170f2ea3

    TX(4aad85735e777795d24aa3eab51be959d8ebdf9683083d85b66f70b7170f2ea3)
    Type:          TxTypeChainDataAnchoring
    From:          0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B
    Nonce:         1234
    GasPrice:      0x19
    GasLimit:      0xf4240
    Signature:     [{"V":"0x25","R":"0xe58b9abf9f33a066b998fccaca711553fb4df425c9234bbb3577f9d9775bb124","S":"0x2c409a6c5d92277c0a812dd0cc553d7fe1d652a807274c3786df3292cd473e09"}]
    Hex:           48f9010e8204d219830f424094a94f5374fce5edbc8e2a8697c15331677e6ebf0bb8a8f8a6a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000405f845f84325a0e58b9abf9f33a066b998fccaca711553fb4df425c9234bbb3577f9d9775bb124a02c409a6c5d92277c0a812dd0cc553d7fe1d652a807274c3786df3292cd473e09
    AnchoredData:  f8a6a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000405
```

### RPC Output (Example) <a href="#rpc-output-example" id="rpc-output-example"></a>

The following shows a transaction object returned via JSON RPC.

```javascript
{
  "blockHash": "0x82983fe294d286e76486760e6904369285554e1744af16786c2393a956fb4ec4",
  "blockNumber": "0x2",
  "contractAddress": null,
  "from": "0x0fcda0f2efbe1b4e61b487701ce4f2f8abc3723d",
  "gas": "0x174876e800",
  "gasPrice": "0x5d21dba00",
  "gasUsed": "0x93a8",
  "input": "0xf8a6a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000405",
  "logs": [],
  "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "nonce": "0x13",
  "senderTxHash": "0x28b56268d18b116b08b1673caad80212f271d6e36ceef225b44c6d2a1f0413db",
  "signatures": [
    {
      "V": "0x26",
      "R": "0x7049656869a9442d26ed0c2cbf15812dc486580d03f1cc6373104410225e1e7b",
      "S": "0x3c58fd9ae9390e6484e965572821846445983d9b5eb7866aa4113c56a5bf253e"
    }
  ],
  "status": "0x1",
  "transactionHash": "0x28b56268d18b116b08b1673caad80212f271d6e36ceef225b44c6d2a1f0413db",
  "transactionIndex": "0xc",
  "type": "TxTypeChainDataAnchoring",
  "typeInt": 72
}
```


# 수수료 위임 트랜잭션

## TxTypeFeeDelegatedValueTransfer <a href="#txtypefeedelegatedvaluetransfer" id="txtypefeedelegatedvaluetransfer"></a>

TxTypeFeeDelegatedValueTransfer는 사용자가 KLAY를 보내려고 할 때 사용됩니다. Klaytn은 각 목적에 맞는 여러가지 트랜잭션 유형들을 제공하는데, TxTypeFeeDelegatedValueTransfer는 KLAY를 EOA에 전송할 때 사용하는 기능입니다. 따라서 TxTypeFeeDelegatedValueTransfer는 `to`가 EOA일때만 작동합니다. KLAY를 스마트 컨트랙트로 전송하려면 [TxTypeFeeDelegatedSmartContractExecution](#txtypefeedelegatedsmartcontractexecution)를 대신 사용하여야 합니다. The following changes will be made by this transaction type.

1. 트랜잭션 수수료 납부자의 잔고는 트랜잭션 수수료만큼 감소합니다.
2. The sender's nonce increases by one.
3. `value` KLAY is transferred from the sender to the recipient.

### Attributes <a href="#attributes" id="attributes"></a>

| Attribute          | Type                                      | Description                                                                                                                                                                                                                                                                                                                                        |
| ------------------ | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| type               | uint8 (Go)                                | TxTypeFeeDelegatedValueTransfer의 유형입니다. 이는 0x09이어야 합니다.                                                                                                                                                                                                                                                                                            |
| nonce              | uint64 (Go)                               | A value used to uniquely identify a sender’s transaction. If two transactions with the same nonce are generated by a sender, only one is executed.                                                                                                                                                                                                 |
| gasPrice           | \*big.Int (Go)                            | A unit price of gas in `peb` the sender will pay for a transaction fee. The amount of transaction fee is calculated as `gas` \* `gasPrice`. For example, if the transaction consumes 10 units of gas and gasPrice is 10^18, the transaction fee will be 10 KLAY. See [Unit of KLAY](/content/klaytn/design/klaytn-native-coin-klay#units-of-klay). |
| gas                | uint64 (Go)                               | The maximum amount of gas the transaction is allowed to use.                                                                                                                                                                                                                                                                                       |
| to                 | common.Address (Go)                       | The account address that will receive the transferred value.                                                                                                                                                                                                                                                                                       |
| value              | \*big.Int (Go)                            | The amount of KLAY in `peb` to be transferred.                                                                                                                                                                                                                                                                                                     |
| from               | common.Address (Go)                       | The address of the sender. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                 |
| txSignatures       | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The sender's signatures. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                   |
| feePayer           | common.Address (Go)                       | 트랜잭션 수수료 납부자의 주소입니다.                                                                                                                                                                                                                                                                                                                               |
| feePayerSignatures | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | 트랜잭션 수수료 납부자의 서명입니다.                                                                                                                                                                                                                                                                                                                               |

### 발신자의 서명을 위한 RLP 인코딩 <a href="#rlp-encoding-for-signature-of-the-sender" id="rlp-encoding-for-signature-of-the-sender"></a>

발신자의 서명을 만들려면 다음과 같이 RLP 직렬화를 수행해야 합니다.

```javascript
SigRLP = encode([encode([type, nonce, gasPrice, gas, to, value, from]), chainid, 0, 0])
SigHash = keccak256(SigRLP)
Signature = sign(SigHash, <the sender's private key>)
```

### 수수료 납부자의 서명을 위한 RLP 인코딩 <a href="#rlp-encoding-for-signature-of-the-fee-payer" id="rlp-encoding-for-signature-of-the-fee-payer"></a>

수수료 납부자의 서명을 만들려면 RLP 직렬화를 다음과 같이 수행해야 합니다.

```javascript
SigFeePayerRLP = encode([ encode([type, nonce, gasPrice, gas, to, value, from]), feePayer, chainid, 0, 0 ])
SigFeePayerHash = keccak256(SigFeePayerRLP)
SignatureFeePayer = sign(SigFeePayerHash, <the fee payer's private key>)
```

### RLP Encoding for SenderTxHash <a href="#rlp-encoding-for-sendertxhash" id="rlp-encoding-for-sendertxhash"></a>

To make a SenderTxHash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
SenderTxHashRLP = type + encode([nonce, gasPrice, gas, to, value, from, txSignatures])
SenderTxHash = keccak256(SenderTxHashRLP)
```

### RLP Encoding for Transaction Hash <a href="#rlp-encoding-for-transaction-hash" id="rlp-encoding-for-transaction-hash"></a>

To make a transaction hash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
feePayerSignatures (a single signature) = [[v, r, s]]
feePayerSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
TxHashRLP = type + encode([nonce, gasPrice, gas, to, value, from, txSignatures, feePayer, feePayerSignatures])`
TxHash = keccak256(TxHashRLP)
```

### RLP Encoding (Example) <a href="#rlp-encoding-example" id="rlp-encoding-example"></a>

The following shows the result of RLP serialization and the transaction object:

```javascript
ChainID 0x1
PrivateKey 0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8
PublicKey.X 0x3a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d
PublicKey.Y 0x8072e77939dc03ba44790779b7a1025baf3003f6732430e20cd9b76d953391b3
SigRLP 0xf839b5f4098204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0b018080
SigHash 0xb86e4cc0955f7c2cda1b36038c9d43a2724fc956c11e09c37625379b7eb2bd21
Signature f845f84325a09f8e49e2ad84b0732984398749956e807e4b526c786af3c5f7416b293e638956a06bf88342092f6ff9fabe31739b2ebfa1409707ce54a54693e91a6b9bb77df0e7
FeePayerPrivateKey 0xb9d5558443585bca6f225b935950e3f6e69f9da8a5809a83f51c3365dff53936
FeePayerPublicKey.X 0x327434d4cfc66ef8857d431419e9deebdc53a3e415edcc55382e2d417b8dd102
FeePayerPublicKey.Y 0x65fc97045707faf7b8f81ac65089d4cc71f69ad0bf1bc8559bc24f13fc284ced
SigRLPFeePayer 0xf84eb5f4098204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0b945a0043070275d9f6054307ee7348bd660849d90f018080
SigHashFeePayer 0x3e7c5f40e826d1d22493be59bf62928dc397de5c972bd9bfa3fe5206c24a5f82
SignatureFeePayer f845f84326a0f45cf8d7f88c08e6b6ec0b3b562f34ca94283e4689021987abb6b0772ddfd80aa0298fe2c5aeabb6a518f4cbb5ff39631a5d88be505d3923374f65fdcf63c2955b
TxHashRLP 0x09f8d68204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0bf845f84325a09f8e49e2ad84b0732984398749956e807e4b526c786af3c5f7416b293e638956a06bf88342092f6ff9fabe31739b2ebfa1409707ce54a54693e91a6b9bb77df0e7945a0043070275d9f6054307ee7348bd660849d90ff845f84326a0f45cf8d7f88c08e6b6ec0b3b562f34ca94283e4689021987abb6b0772ddfd80aa0298fe2c5aeabb6a518f4cbb5ff39631a5d88be505d3923374f65fdcf63c2955b
TxHash e1e07f9971153499fc8c7bafcdaf7abc20b37aa4c18fb1e53a9bfcc259e3644c
SenderTxHashRLP 0x09f87a8204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0bf845f84325a09f8e49e2ad84b0732984398749956e807e4b526c786af3c5f7416b293e638956a06bf88342092f6ff9fabe31739b2ebfa1409707ce54a54693e91a6b9bb77df0e7
SenderTxHash 40f8c94e01e07eb5353f6cd4cd3eabd5893215dd53a50ba4b8ff9a447ac51731

    TX(e1e07f9971153499fc8c7bafcdaf7abc20b37aa4c18fb1e53a9bfcc259e3644c)
    Type:          TxTypeFeeDelegatedValueTransfer
    From:          0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B
    To:            0x7b65B75d204aBed71587c9E519a89277766EE1d0
    Nonce:         1234
    GasPrice:      0x19
    GasLimit:      0xf4240
    Value:         0xa
    Signature:     [{"V":"0x25","R":"0x9f8e49e2ad84b0732984398749956e807e4b526c786af3c5f7416b293e638956","S":"0x6bf88342092f6ff9fabe31739b2ebfa1409707ce54a54693e91a6b9bb77df0e7"}]
    FeePayer:      0x5A0043070275d9f6054307Ee7348bD660849D90f
    FeePayerSig:   [{"V":"0x26","R":"0xf45cf8d7f88c08e6b6ec0b3b562f34ca94283e4689021987abb6b0772ddfd80a","S":"0x298fe2c5aeabb6a518f4cbb5ff39631a5d88be505d3923374f65fdcf63c2955b"}]
    Hex:           09f8d68204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0bf845f84325a09f8e49e2ad84b0732984398749956e807e4b526c786af3c5f7416b293e638956a06bf88342092f6ff9fabe31739b2ebfa1409707ce54a54693e91a6b9bb77df0e7945a0043070275d9f6054307ee7348bd660849d90ff845f84326a0f45cf8d7f88c08e6b6ec0b3b562f34ca94283e4689021987abb6b0772ddfd80aa0298fe2c5aeabb6a518f4cbb5ff39631a5d88be505d3923374f65fdcf63c2955b
```

### RPC Output (Example) <a href="#rpc-output-example" id="rpc-output-example"></a>

The following shows a transaction object returned via JSON RPC.

```javascript
{
  "blockHash": "0x7ad6ed1f9955be00db8fb5452125f0e9a3c0856abb5b4cc4aed91ffc134321da",
  "blockNumber": "0x1",
  "contractAddress": null,
  "feePayer": "0x029fdce0457db02f05c4be9f67b7115cb8ea15ca",
  "feePayerSignatures": [
    {
      "V": "0x26",
      "R": "0x984e9d43c496ef39ef2d496c8e1aee695f871e4f6cfae7f205ddda1589ca5c9e",
      "S": "0x46647d1ce8755cd664f5fb4eba3082dd1a13817488029f3869662986b7b1a5ae"
    }
  ],
  "from": "0x0fcda0f2efbe1b4e61b487701ce4f2f8abc3723d",
  "gas": "0x174876e800",
  "gasPrice": "0x5d21dba00",
  "gasUsed": "0x7918",
  "logs": [],
  "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "nonce": "0x2",
  "senderTxHash": "0x6a8cf9a2f6d16561303445309d4f210c8be862f0d0c0e6f4998775fef9b4f957",
  "signatures": [
    {
      "V": "0x25",
      "R": "0x368b3324b37831b51711a2eba2a7608438a2bd5956ccecbcdb07d9163ff8bc87",
      "S": "0x7ee2e86ad6f01c867b2ced9d69e614ba22e539726451400fccdd56acbbc7a6f7"
    }
  ],
  "status": "0x1",
  "to": "0x75c3098be5e4b63fbac05838daaee378dd48098d",
  "transactionHash": "0xea4341b5c95fd5a0c3a8a15a4177ab6394725c24f722a9e31f53474a6dcf086a",
  "transactionIndex": "0x2",
  "type": "TxTypeFeeDelegatedValueTransfer",
  "typeInt": 9,
  "value": "0x21e19e0c9bab2400000"
}
```

## TxTypeFeeDelegatedValueTransferMemo <a href="#txtypefeedelegatedvaluetransfermemo" id="txtypefeedelegatedvaluetransfermemo"></a>

TxTypeFeeDelegatedValueTransferMemo는 사용자가 특정 메시지와 함께 KLAY를 보내려고 할 때 사용됩니다. 따라서 TxTypeFeeDelegatedValueTransferMemo는 `to`가 EOA일때만 작동합니다. To transfer KLAY to a smart contract account, use [TxTypeFeeDelegatedSmartContractExecution](#txtypefeedelegatedsmartcontractexecution) instead. The following changes will be made by this transaction type.

1. The fee payer's balance decreases by the amount of the transaction fee.
2. The sender's nonce increases by one.
3. `value` KLAY is transferred from the sender to the recipient.

### Attributes <a href="#attributes" id="attributes"></a>

| Attribute          | Description                               | Type                                                                                                                                                                                                                                                                                                                                               | 예제 값 |
| ------------------ | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- |
| type               | uint8 (Go)                                | TxTypeFeeDelegatedValueTransferMemo의 유형입니다. 이는 0x11이어야 합니다.                                                                                                                                                                                                                                                                                        |      |
| nonce              | uint64 (Go)                               | A value used to uniquely identify a sender’s transaction. If two transactions with the same nonce are generated by a sender, only one is executed.                                                                                                                                                                                                 |      |
| gasPrice           | \*big.Int (Go)                            | A unit price of gas in `peb` the sender will pay for a transaction fee. The amount of transaction fee is calculated as `gas` \* `gasPrice`. For example, if the transaction consumes 10 units of gas and gasPrice is 10^18, the transaction fee will be 10 KLAY. See [Unit of KLAY](/content/klaytn/design/klaytn-native-coin-klay#units-of-klay). |      |
| gas                | uint64 (Go)                               | The maximum amount of gas the transaction is allowed to use.                                                                                                                                                                                                                                                                                       |      |
| to                 | common.Address (Go)                       | The account address that will receive the transferred value.                                                                                                                                                                                                                                                                                       |      |
| value              | \*big.Int (Go)                            | The amount of KLAY in `peb` to be transferred.                                                                                                                                                                                                                                                                                                     |      |
| from               | common.Address (Go)                       | The address of the sender. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                 |      |
| input              | \[]byte (Go)                              | Data attached to the transaction. The message should be passed to this attribute.                                                                                                                                                                                                                                                                  |      |
| txSignatures       | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The sender's signatures. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                   |      |
| feePayer           | common.Address (Go)                       | The address of the fee payer.                                                                                                                                                                                                                                                                                                                      |      |
| feePayerSignatures | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The fee payer's signatures.                                                                                                                                                                                                                                                                                                                        |      |

### RLP Encoding for Signature of the Sender <a href="#rlp-encoding-for-signature-of-the-sender" id="rlp-encoding-for-signature-of-the-sender"></a>

To make a signature of the sender, RLP serialization should be done like the following:

```javascript
SigRLP = encode([encode([type, nonce, gasPrice, gas, to, value, from, input]), chainid, 0, 0])
SigHash = keccak256(SigRLP)
Signature = sign(SigHash, <the sender's private key>)
```

### RLP Encoding for Signature of the Fee Payer <a href="#rlp-encoding-for-signature-of-the-fee-payer" id="rlp-encoding-for-signature-of-the-fee-payer"></a>

To make a signature of the fee payer, RLP serialization should be done like the following:

```javascript
SigFeePayerRLP = encode([encode([type, nonce, gasPrice, gas, to, value, from, input]), feePayer, chainid, 0, 0])
SigFeePayerHash = keccak256(SigFeePayerRLP)
SignatureFeePayer = sign(SigFeePayerHash, <the fee payer's private key>)
```

### RLP Encoding for SenderTxHash <a href="#rlp-encoding-for-sendertxhash" id="rlp-encoding-for-sendertxhash"></a>

To make a SenderTxHash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
SenderTxHashRLP = type + encode([nonce, gasPrice, gas, to, value, from, input, txSignatures])
SenderTxHash = keccak256(SenderTxHashRLP)
```

### RLP Encoding for Transaction Hash <a href="#rlp-encoding-for-transaction-hash" id="rlp-encoding-for-transaction-hash"></a>

To make a transaction hash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
feePayerSignatures (a single signature) = [[v, r, s]]
feePayerSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
TxHashRLP = type + encode([nonce, gasPrice, gas, to, value, from, input, txSignatures, feePayer, feePayerSignatures])
TxHash = keccak256(TxHashRLP)
```

### RLP Encoding (Example) <a href="#rlp-encoding-example" id="rlp-encoding-example"></a>

The following shows the result of RLP serialization and the transaction object:

```javascript
ChainID 0x1
PrivateKey 0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8
PublicKey.X 0x3a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d
PublicKey.Y 0x8072e77939dc03ba44790779b7a1025baf3003f6732430e20cd9b76d953391b3
SigRLP 0xf841b83cf83a118204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0b8568656c6c6f018080
SigHash 0x3333b9336d431ffa53b795fedcf03cc2217cea3f26825ea5cbf7d69f0b99fde9
Signature f845f84326a064e213aef0167fbd853f8f9989ef5d8b912a77457395ccf13d7f37009edd5c5ba05d0c2e55e4d8734fe2516ed56ac628b74c0eb02aa3b6eda51e1e25a1396093e1
FeePayerPrivateKey 0xb9d5558443585bca6f225b935950e3f6e69f9da8a5809a83f51c3365dff53936
FeePayerPublicKey.X 0x327434d4cfc66ef8857d431419e9deebdc53a3e415edcc55382e2d417b8dd102
FeePayerPublicKey.Y 0x65fc97045707faf7b8f81ac65089d4cc71f69ad0bf1bc8559bc24f13fc284ced
SigRLPFeePayer 0xf856b83cf83a118204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0b8568656c6c6f945a0043070275d9f6054307ee7348bd660849d90f018080
SigHashFeePayer 0xed015096fb27764f576415e23576228cbf7c4fdad464ea7ffc3a1856dfe391c9
SignatureFeePayer f845f84326a087390ac14d3c34440b6ddb7b190d3ebde1a07d9a556e5a82ce7e501f24a060f9a037badbcb12cda1ed67b12b1831683a08a3adadee2ea760a07a46bdbb856fea44
TxHashRLP 0x11f8dc8204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0b8568656c6c6ff845f84326a064e213aef0167fbd853f8f9989ef5d8b912a77457395ccf13d7f37009edd5c5ba05d0c2e55e4d8734fe2516ed56ac628b74c0eb02aa3b6eda51e1e25a1396093e1945a0043070275d9f6054307ee7348bd660849d90ff845f84326a087390ac14d3c34440b6ddb7b190d3ebde1a07d9a556e5a82ce7e501f24a060f9a037badbcb12cda1ed67b12b1831683a08a3adadee2ea760a07a46bdbb856fea44
TxHash 8f68882f6192a53ba470aeca1e83ed9b9e519906a91256724b284dee778b21c9
SenderTxHashRLP 0x11f8808204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0b8568656c6c6ff845f84326a064e213aef0167fbd853f8f9989ef5d8b912a77457395ccf13d7f37009edd5c5ba05d0c2e55e4d8734fe2516ed56ac628b74c0eb02aa3b6eda51e1e25a1396093e1
SenderTxHash fffaa2b38d4e684ea70a89c78fc7b2659000d130c76ad721d68175cbfc77c550

    TX(8f68882f6192a53ba470aeca1e83ed9b9e519906a91256724b284dee778b21c9)
    Type:          TxTypeFeeDelegatedValueTransferMemo
    From:          0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B
    To:            0x7b65B75d204aBed71587c9E519a89277766EE1d0
    Nonce:         1234
    GasPrice:      0x19
    GasLimit:      0xf4240
    Value:         0xa
    Signature:     [{"V":"0x26","R":"0x64e213aef0167fbd853f8f9989ef5d8b912a77457395ccf13d7f37009edd5c5b","S":"0x5d0c2e55e4d8734fe2516ed56ac628b74c0eb02aa3b6eda51e1e25a1396093e1"}]
    FeePayer:      0x5A0043070275d9f6054307Ee7348bD660849D90f
    FeePayerSig:   [{"V":"0x26","R":"0x87390ac14d3c34440b6ddb7b190d3ebde1a07d9a556e5a82ce7e501f24a060f9","S":"0x37badbcb12cda1ed67b12b1831683a08a3adadee2ea760a07a46bdbb856fea44"}]
    Data:          36383635366336633666
    Hex:           11f8dc8204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0b8568656c6c6ff845f84326a064e213aef0167fbd853f8f9989ef5d8b912a77457395ccf13d7f37009edd5c5ba05d0c2e55e4d8734fe2516ed56ac628b74c0eb02aa3b6eda51e1e25a1396093e1945a0043070275d9f6054307ee7348bd660849d90ff845f84326a087390ac14d3c34440b6ddb7b190d3ebde1a07d9a556e5a82ce7e501f24a060f9a037badbcb12cda1ed67b12b1831683a08a3adadee2ea760a07a46bdbb856fea44
```

### RPC Output (Example) <a href="#rpc-output-example" id="rpc-output-example"></a>

The following shows a transaction object returned via JSON RPC.

```javascript
{
  "blockHash": "0x7ad6ed1f9955be00db8fb5452125f0e9a3c0856abb5b4cc4aed91ffc134321da",
  "blockNumber": "0x1",
  "contractAddress": null,
  "feePayer": "0x029fdce0457db02f05c4be9f67b7115cb8ea15ca",
  "feePayerSignatures": [
    {
      "V": "0x25",
      "R": "0xb5d80dc924c51f58eb674a142ebfd8ca1c0bc722bc85b001a5a6905ba8226b1",
      "S": "0x79852418faacd4407aee4a461a08602fcf6a3a3cb63b9ba69d70ffe2f5fe3cd"
    }
  ],
  "from": "0x0fcda0f2efbe1b4e61b487701ce4f2f8abc3723d",
  "gas": "0x174876e800",
  "gasPrice": "0x5d21dba00",
  "gasUsed": "0x7b0c",
  "input": "0x68656c6c6f",
  "logs": [],
  "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "nonce": "0x5",
  "senderTxHash": "0x5a4e42bac0b2bc8dda4ee82bfafc83e7f156f74d81d367a3db430abd40b2cd47",
  "signatures": [
    {
      "V": "0x26",
      "R": "0xe8f5484b057b542c80f16c5bb8707e040619c3dc9ac5628d2797aa3d8a2fc0d0",
      "S": "0x5d598f2f10283ded6f6e6a216f4278b27fdf4d431272fa090064ac0fd3fc8102"
    }
  ],
  "status": "0x1",
  "to": "0x75c3098be5e4b63fbac05838daaee378dd48098d",
  "transactionHash": "0x66fe4d1abdf15a250f9391646e0242c8e4c3310250ca316d8fd00856aac16172",
  "transactionIndex": "0x5",
  "type": "TxTypeFeeDelegatedValueTransferMemo",
  "typeInt": 17,
  "value": "0x989680"
}
```

## TxTypeFeeDelegatedSmartContractDeploy <a href="#txtypefeedelegatedsmartcontractdeploy" id="txtypefeedelegatedsmartcontractdeploy"></a>

TxTypeFeeDelegatedSmartContractDeploy는 트랜잭션 수수료를 위임하는 스마트 컨트랙트를 배포합니다. The following changes will be made by this transaction type.

1. The fee payer's balance decreases by the amount of the transaction fee.
2. The sender's nonce increases by one.
3. A smart contract is deployed with the code in `input`. The deployed address will be returned via `contractAddress` in the receipt.
4. `value` KLAY is transferred from the sender to the recipient.

### Attributes <a href="#attributes" id="attributes"></a>

| Attribute          | Type                                      | Description                                                                                                                                                                                                                                                                                                                                        |
| ------------------ | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| type               | uint8 (Go)                                | TxTypeFeeDelegatedSmartContractDeploy의 유형입니다. 이는 0x29이어야 합니다.                                                                                                                                                                                                                                                                                      |
| nonce              | uint64 (Go)                               | A value used to uniquely identify a sender’s transaction. If two transactions with the same nonce are generated by a sender, only one is executed.                                                                                                                                                                                                 |
| gasPrice           | \*big.Int (Go)                            | A unit price of gas in `peb` the sender will pay for a transaction fee. The amount of transaction fee is calculated as `gas` \* `gasPrice`. For example, if the transaction consumes 10 units of gas and gasPrice is 10^18, the transaction fee will be 10 KLAY. See [Unit of KLAY](/content/klaytn/design/klaytn-native-coin-klay#units-of-klay). |
| gas                | uint64 (Go)                               | The maximum amount of gas the transaction is allowed to use.                                                                                                                                                                                                                                                                                       |
| to                 | \*common.Address (Go)                     | The account address that will receive the transferred value. Currently, this value must be nil. Specifying the address will be supported in the future.                                                                                                                                                                                            |
| value              | \*big.Int (Go)                            | The amount of KLAY in `peb` to be transferred.                                                                                                                                                                                                                                                                                                     |
| from               | common.Address (Go)                       | The address of the sender. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                 |
| input              | \[]byte (Go)                              | Data attached to the transaction, used for transaction execution.                                                                                                                                                                                                                                                                                  |
| humanReadable      | bool (Go)                                 | This must be false since human-readable address is not supported yet. If true, the transaction will be rejected.                                                                                                                                                                                                                                   |
| codeFormat         | uint8 (Go)                                | The code format of smart contract code. The supported value for now is EVM(0x00) only.                                                                                                                                                                                                                                                             |
| txSignatures       | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The sender's signatures. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                   |
| feePayer           | common.Address (Go)                       | The address of the fee payer.                                                                                                                                                                                                                                                                                                                      |
| feePayerSignatures | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The fee payer's signatures.                                                                                                                                                                                                                                                                                                                        |

### RLP Encoding for Signature of the Sender <a href="#rlp-encoding-for-signature-of-the-sender" id="rlp-encoding-for-signature-of-the-sender"></a>

To make a signature of the sender, RLP serialization should be done like the following:

```javascript
SigRLP = encode([encode([type, nonce, gasPrice, gas, to, value, from, input, humanReadable, codeFormat]), chainid, 0, 0])
SigHash = keccak256(SigRLP)
Signature = sign(SigHash, <the sender's private key>)
```

### RLP Encoding for Signature of the Fee Payer <a href="#rlp-encoding-for-signature-of-the-fee-payer" id="rlp-encoding-for-signature-of-the-fee-payer"></a>

To make a signature of the fee payer, RLP serialization should be done like the following:

```javascript
SigFeePayerRLP = encode([encode([type, nonce, gasPrice, gas, to, value, from, input, humanReadable, codeFormat]), feePayer, chainid, 0, 0])
SigFeePayerHash = keccak256(SigFeePayerRLP)
SignatureFeePayer = sign(SigFeePayerHash, <the fee payer's private key>)
```

### RLP Encoding for SenderTxHash <a href="#rlp-encoding-for-sendertxhash" id="rlp-encoding-for-sendertxhash"></a>

To make a SenderTxHash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
SenderTxHashRLP = type + encode([nonce, gasPrice, gas, to, value, from, input,humanReadable, codeFormat, txSignatures])
SenderTxHash = keccak256(SenderTxHashRLP)
```

### RLP Encoding for Transaction Hash <a href="#rlp-encoding-for-transaction-hash" id="rlp-encoding-for-transaction-hash"></a>

To make a transaction hash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
feePayerSignatures (a single signature) = [[v, r, s]]
feePayerSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
TxHashRLP = type + encode([nonce, gasPrice, gas, to, value, from, input, humanReadable, codeFormat, txSignatures, feePayer, feePayerSignatures])
TxHash = keccak256(TxHashRLP)
```

### RLP Encoding (Example) <a href="#rlp-encoding-example" id="rlp-encoding-example"></a>

The following shows the result of RLP serialization and the transaction object:

```javascript
ChainID 0x1
PrivateKey 0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8
PublicKey.X 0x3a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d
PublicKey.Y 0x8072e77939dc03ba44790779b7a1025baf3003f6732430e20cd9b76d953391b3
SigRLP 0xf90240b9023af90237298204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0bb901fe608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f00290180018080
SigHash 0xfd5e0726c763d117d07e5e688889ab7e4d0d1164d1bbca26a9d4ee629cbd875b
Signature f845f84325a04ea37b8ecfed93795a9f99b1e4d554df6fb05a361965a7655abd4e4c4422a9e5a00b05e3fffe5a3c0892eaff31466f6c47b7edad80703d395d65bbfc1a2c6a2570
FeePayerPrivateKey 0xb9d5558443585bca6f225b935950e3f6e69f9da8a5809a83f51c3365dff53936
FeePayerPublicKey.X 0x327434d4cfc66ef8857d431419e9deebdc53a3e415edcc55382e2d417b8dd102
FeePayerPublicKey.Y 0x65fc97045707faf7b8f81ac65089d4cc71f69ad0bf1bc8559bc24f13fc284ced
SigRLPFeePayer 0xf90255b9023af90237298204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0bb901fe608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f00290180945a0043070275d9f6054307ee7348bd660849d90f018080
SigHashFeePayer 0xb7ea4d9d8c4d20ac6fd6cfffcaf89ae7d217d7450820b3b40d9ea29a0f01a1b2
SignatureFeePayer f845f84326a0c6738376304dfb32c77649bddd4ade925b947876cfe6b1fd2c06a2e4394504cca023817ba66a6b7c92fcf23f2d5506ea2a673aae5f1a1e4d742367971ae58a1576
TxHashRLP 0x29f902d98204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0bb901fe608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f00290180f845f84325a04ea37b8ecfed93795a9f99b1e4d554df6fb05a361965a7655abd4e4c4422a9e5a00b05e3fffe5a3c0892eaff31466f6c47b7edad80703d395d65bbfc1a2c6a2570945a0043070275d9f6054307ee7348bd660849d90ff845f84326a0c6738376304dfb32c77649bddd4ade925b947876cfe6b1fd2c06a2e4394504cca023817ba66a6b7c92fcf23f2d5506ea2a673aae5f1a1e4d742367971ae58a1576
TxHash a457cc54b5cfd35eb61baa5ad61398fdcecab4c83693815addf00ca7166cb87e
SenderTxHashRLP 0x29f9027d8204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0bb901fe608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f00290180f845f84325a04ea37b8ecfed93795a9f99b1e4d554df6fb05a361965a7655abd4e4c4422a9e5a00b05e3fffe5a3c0892eaff31466f6c47b7edad80703d395d65bbfc1a2c6a2570
SenderTxHash f3bca26fc8b50bfbcc1e94bc792ee6489cff14056e7e9aa2b074abb385f2139f

    TX(a457cc54b5cfd35eb61baa5ad61398fdcecab4c83693815addf00ca7166cb87e)
    Type:          TxTypeFeeDelegatedSmartContractDeploy
    From:          0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B
    To:            0x7b65B75d204aBed71587c9E519a89277766EE1d0
    Nonce:         1234
    GasPrice:      0x19
    GasLimit:      0xf4240
    Value:         0xa
    Data:          363038303630343035323334383031353631303031303537363030303830666435623530363130316465383036313030323036303030333936303030663330303630383036303430353236303034333631303631303036313537363366666666666666663763303130303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303630303033353034313636333161333964386566383131343631303038303537383036333633353335383662313436313030613735373830363337306130383233313134363130306361353738303633666436623765663831343631303066383537356233333630303039303831353236303031363032303532363034303831323038303534333439303831303139303931353538313534303139303535303035623334383031353631303038633537363030303830666435623530363130303935363130313064353635623630343038303531393138323532353139303831393030333630323030313930663335623631303063383733666666666666666666666666666666666666666666666666666666666666666666666666666666663630303433353136363130313133353635623030356233343830313536313030643635373630303038306664356235303631303039353733666666666666666666666666666666666666666666666666666666666666666666666666666666663630303433353136363130313437353635623334383031353631303130343537363030303830666435623530363130306338363130313539353635623630303035343831353635623733666666666666666666666666666666666666666666666666666666666666666666666666666666663136363030303930383135323630303136303230353236303430383132303830353433343930383130313930393135353831353430313930353535363562363030313630323035323630303039303831353236303430393032303534383135363562333336303030393038313532363030313630323035323630343038313230383035343930383239303535393038313131313536313031616635373630343035313333393038323135363130386663303239303833393036303030383138313831383538383838663139333530353035303530313536313031396335373631303161663536356233333630303039303831353236303031363032303532363034303930323038313930353535623530353630306131363536323761376137323330353832303632376361343662623039343738613031353736323830366363303063343331323330353031313138633763323663333061633538633465303965353163346630303239
    HumanReadable: true
    CodeFormat:    CodeFormatEVM
    Signature:     [{"V":"0x25","R":"0x4ea37b8ecfed93795a9f99b1e4d554df6fb05a361965a7655abd4e4c4422a9e5","S":"0xb05e3fffe5a3c0892eaff31466f6c47b7edad80703d395d65bbfc1a2c6a2570"}]
    FeePayer:      0x5A0043070275d9f6054307Ee7348bD660849D90f
    FeePayerSig:   [{"V":"0x26","R":"0xc6738376304dfb32c77649bddd4ade925b947876cfe6b1fd2c06a2e4394504cc","S":"0x23817ba66a6b7c92fcf23f2d5506ea2a673aae5f1a1e4d742367971ae58a1576"}]
    Hex:           29f902d98204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0bb901fe608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f00290180f845f84325a04ea37b8ecfed93795a9f99b1e4d554df6fb05a361965a7655abd4e4c4422a9e5a00b05e3fffe5a3c0892eaff31466f6c47b7edad80703d395d65bbfc1a2c6a2570945a0043070275d9f6054307ee7348bd660849d90ff845f84326a0c6738376304dfb32c77649bddd4ade925b947876cfe6b1fd2c06a2e4394504cca023817ba66a6b7c92fcf23f2d5506ea2a673aae5f1a1e4d742367971ae58a1576
```

### RPC Output (Example) <a href="#rpc-output-example" id="rpc-output-example"></a>

The following shows a transaction object returned via JSON RPC.

```javascript
{
  "blockHash": "0x82983fe294d286e76486760e6904369285554e1744af16786c2393a956fb4ec4",
  "blockNumber": "0x2",
  "codeFormat": "0x0",
  "contractAddress": "0x636f6e7472616374322e6b6c6179746e00000000",
  "feePayer": "0x029fdce0457db02f05c4be9f67b7115cb8ea15ca",
  "feePayerSignatures": [
    {
      "V": "0x25",
      "R": "0x614fd887f4702627156132c9d56584207d1eaff529ee2967431eeaba924678f9",
      "S": "0x6b883a4467ca95a0ee75567062cb6d35629e9a22faeb8a711896488ce2cc4ed9"
    }
  ],
  "from": "0x0fcda0f2efbe1b4e61b487701ce4f2f8abc3723d",
  "gas": "0x174876e800",
  "gasPrice": "0x0",
  "gasUsed": "0xee6e5b4d",
  "humanReadable": true,
  "input": "0x608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f0029",
  "logs": [],
  "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "nonce": "0xb",
  "senderTxHash": "0xf8f83c7a4a334430f403b20d84db492fac43ebabbd9676d731e11460d01a2160",
  "signatures": [
    {
      "V": "0x26",
      "R": "0xf3c521fea307b39bfa914b4835112bad18f89a627d639ddabe70c20af99d29a5",
      "S": "0x5179048cf993049b380f8cf7017c6e83b23da7883d2728208fe6161808594f44"
    }
  ],
  "status": "0x1",
  "to": "0x636f6e7472616374322e6b6c6179746e00000000",
  "transactionHash": "0x39b8a31f0c02a951615e3497d68a6534b8c8cc565e514ceafec53ee7ff50b8d9",
  "transactionIndex": "0x4",
  "type": "TxTypeFeeDelegatedSmartContractDeploy",
  "typeInt": 41,
  "value": "0x0"
}
```

## TxTypeFeeDelegatedSmartContractExecution <a href="#txtypefeedelegatedsmartcontractexecution" id="txtypefeedelegatedsmartcontractexecution"></a>

TxTypeFeeDelegatedSmartContractExecution는 스마트 컨트랙트를 실행하고, `input`에 입력된 데이터를 이용합니다. 트랜잭션 수수료는 지정된 수수료 납부자가 지불합니다. TxTypeFeeDelegatedSmartContractExecution는 `to`가 스마트 컨트랙트 계정일 때만 실행됩니다. KLAY를 외부 소유 계정으로 전송하려면 [TxTypeFeeDelegatedValueTransfer](#txtypefeedelegatedvaluetransfer)를 대신 사용하십시오. The following changes will be made by this transaction type.

1. If `to` is a smart contract account, the code is executed based on `input`. Otherwise, this transaction will be rejected.
2. The fee payer's balance decreases by the amount of the transaction fee.
3. The sender's nonce increases by one.
4. If `value` was provided, `value` KLAY is transferred from the sender to the `to` smart contract. The contract should have a payable fallback function to receive KLAY.

### Attributes <a href="#attributes" id="attributes"></a>

| Attribute          | Type                                      | Description                                                                                                                                                                                                                                                                                                                                        |
| ------------------ | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| type               | uint8 (Go)                                | TxTypeFeeDelegatedSmartContractExecution의 유형입니다. 이는 0x31이어야 합니다.                                                                                                                                                                                                                                                                                   |
| nonce              | uint64 (Go)                               | A value used to uniquely identify a sender’s transaction. If two transactions with the same nonce are generated by a sender, only one is executed.                                                                                                                                                                                                 |
| gasPrice           | \*big.Int (Go)                            | A unit price of gas in `peb` the sender will pay for a transaction fee. The amount of transaction fee is calculated as `gas` \* `gasPrice`. For example, if the transaction consumes 10 units of gas and gasPrice is 10^18, the transaction fee will be 10 KLAY. See [Unit of KLAY](/content/klaytn/design/klaytn-native-coin-klay#units-of-klay). |
| gas                | uint64 (Go)                               | The maximum amount of gas the transaction is allowed to use.                                                                                                                                                                                                                                                                                       |
| to                 | common.Address (Go)                       | The address of the smart contract account to be executed.                                                                                                                                                                                                                                                                                          |
| value              | \*big.Int (Go)                            | The amount of KLAY in `peb` to be transferred.                                                                                                                                                                                                                                                                                                     |
| from               | common.Address (Go)                       | The address of the sender. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                 |
| input              | \[]byte (Go)                              | Data attached to the transaction, used for transaction execution.                                                                                                                                                                                                                                                                                  |
| txSignatures       | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The sender's signatures. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                   |
| feePayer           | common.Address (Go)                       | The address of the fee payer.                                                                                                                                                                                                                                                                                                                      |
| feePayerSignatures | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The fee payer's signatures.                                                                                                                                                                                                                                                                                                                        |

### RLP Encoding for Signature of the Sender <a href="#rlp-encoding-for-signature-of-the-sender" id="rlp-encoding-for-signature-of-the-sender"></a>

To make a signature of the sender, RLP serialization should be done like the following:

```javascript
SigRLP = encode([encode([type, nonce, gasPrice, gas, to, value, from, input]), chainid, 0, 0])
SigHash = keccak256(SigRLP)
Signature = sign(SigHash, <the sender's private key>)
```

### RLP Encoding for Signature of the Fee Payer <a href="#rlp-encoding-for-signature-of-the-fee-payer" id="rlp-encoding-for-signature-of-the-fee-payer"></a>

To make a signature of the fee payer, RLP serialization should be done like the following:

```javascript
SigFeePayerRLP = encode([encode([type, nonce, gasPrice, gas, to, value, from, input]), feePayer, chainid, 0, 0])
SigFeePayerHash = keccak256(SigFeePayerRLP)
SignatureFeePayer = sign(SigFeePayerHash, <the fee payer's private key>)
```

### RLP Encoding for SenderTxHash <a href="#rlp-encoding-for-sendertxhash" id="rlp-encoding-for-sendertxhash"></a>

To make a SenderTxHash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
SenderTxHashRLP = type + encode([nonce, gasPrice, gas, to, value, from, input, txSignatures])
SenderTxHash = keccak256(SenderTxHashRLP)
```

### RLP Encoding for Transaction Hash <a href="#rlp-encoding-for-transaction-hash" id="rlp-encoding-for-transaction-hash"></a>

To make a transaction hash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
feePayerSignatures (a single signature) = [[v, r, s]]
feePayerSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
TxHashRLP = type + encode([nonce, gasPrice, gas, to, value, from, input, txSignatures, feePayer, feePayerSignatures])
TxHash = keccak256(TxHashRLP)
```

### RLP Encoding (Example) <a href="#rlp-encoding-example" id="rlp-encoding-example"></a>

The following shows the result of RLP serialization and the transaction object:

```javascript
ChainID 0x1
PrivateKey 0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8
PublicKey.X 0x3a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d
PublicKey.Y 0x8072e77939dc03ba44790779b7a1025baf3003f6732430e20cd9b76d953391b3
SigRLP 0xf860b85bf859318204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0ba46353586b000000000000000000000000bc5951f055a85f41a3b62fd6f68ab7de76d299b2018080
SigHash 0xa5dd93af9f96fa316f0ddd84f10acb2e6eb41baaec3b42f9068c38aa1618f7e1
Signature f845f84325a0253aea7d2c37160da45e84afbb45f6b3341cf1e8fc2df4ecc78f14adb512dc4fa022465b74015c2a8f8501186bb5e200e6ce44be52e9374615a7e7e21c41bc27b5
FeePayerPrivateKey 0xb9d5558443585bca6f225b935950e3f6e69f9da8a5809a83f51c3365dff53936
FeePayerPublicKey.X 0x327434d4cfc66ef8857d431419e9deebdc53a3e415edcc55382e2d417b8dd102
FeePayerPublicKey.Y 0x65fc97045707faf7b8f81ac65089d4cc71f69ad0bf1bc8559bc24f13fc284ced
SigRLPFeePayer 0xf875b85bf859318204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0ba46353586b000000000000000000000000bc5951f055a85f41a3b62fd6f68ab7de76d299b2945a0043070275d9f6054307ee7348bd660849d90f018080
SigHashFeePayer 0xf547d9d0041912e0daa2db2b65170a9e833877cd8482f405a11b03429fcbd554
SignatureFeePayer f845f84326a0e7c51db7b922c6fa2a941c9687884c593b1b13076bdf0c473538d826bf7b9d1aa05b0de2aabb84b66db8bf52d62f3d3b71b592e3748455630f1504c20073624d80
TxHashRLP 0x31f8fb8204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0ba46353586b000000000000000000000000bc5951f055a85f41a3b62fd6f68ab7de76d299b2f845f84325a0253aea7d2c37160da45e84afbb45f6b3341cf1e8fc2df4ecc78f14adb512dc4fa022465b74015c2a8f8501186bb5e200e6ce44be52e9374615a7e7e21c41bc27b5945a0043070275d9f6054307ee7348bd660849d90ff845f84326a0e7c51db7b922c6fa2a941c9687884c593b1b13076bdf0c473538d826bf7b9d1aa05b0de2aabb84b66db8bf52d62f3d3b71b592e3748455630f1504c20073624d80
TxHash ef46f28c54b3d90a183e26f406ca1d5cc2b6e9fbb6cfa7c85a10330ffadf54b0
SenderTxHashRLP 0x31f89f8204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0ba46353586b000000000000000000000000bc5951f055a85f41a3b62fd6f68ab7de76d299b2f845f84325a0253aea7d2c37160da45e84afbb45f6b3341cf1e8fc2df4ecc78f14adb512dc4fa022465b74015c2a8f8501186bb5e200e6ce44be52e9374615a7e7e21c41bc27b5
SenderTxHash 3cd3380f4206943422d5d5b218dd66d03d60d19a109f9929ea12b52a230257cb

    TX(ef46f28c54b3d90a183e26f406ca1d5cc2b6e9fbb6cfa7c85a10330ffadf54b0)
    Type:          TxTypeFeeDelegatedSmartContractExecution
    From:          0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B
    To:            0x7b65B75d204aBed71587c9E519a89277766EE1d0
    Nonce:         1234
    GasPrice:      0x19
    GasLimit:      0xf4240
    Value:         0xa
    Data:          363335333538366230303030303030303030303030303030303030303030303062633539353166303535613835663431613362363266643666363861623764653736643239396232
    Signature:     [{"V":"0x25","R":"0x253aea7d2c37160da45e84afbb45f6b3341cf1e8fc2df4ecc78f14adb512dc4f","S":"0x22465b74015c2a8f8501186bb5e200e6ce44be52e9374615a7e7e21c41bc27b5"}]
    FeePayer:      0x5A0043070275d9f6054307Ee7348bD660849D90f
    FeePayerSig:   [{"V":"0x26","R":"0xe7c51db7b922c6fa2a941c9687884c593b1b13076bdf0c473538d826bf7b9d1a","S":"0x5b0de2aabb84b66db8bf52d62f3d3b71b592e3748455630f1504c20073624d80"}]
    Hex:           31f8fb8204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0ba46353586b000000000000000000000000bc5951f055a85f41a3b62fd6f68ab7de76d299b2f845f84325a0253aea7d2c37160da45e84afbb45f6b3341cf1e8fc2df4ecc78f14adb512dc4fa022465b74015c2a8f8501186bb5e200e6ce44be52e9374615a7e7e21c41bc27b5945a0043070275d9f6054307ee7348bd660849d90ff845f84326a0e7c51db7b922c6fa2a941c9687884c593b1b13076bdf0c473538d826bf7b9d1aa05b0de2aabb84b66db8bf52d62f3d3b71b592e3748455630f1504c20073624d80
```

### RPC Output (Example) <a href="#rpc-output-example" id="rpc-output-example"></a>

The following shows a transaction object returned via JSON RPC.

```javascript
{
  "blockHash": "0x82983fe294d286e76486760e6904369285554e1744af16786c2393a956fb4ec4",
  "blockNumber": "0x2",
  "contractAddress": null,
  "feePayer": "0x029fdce0457db02f05c4be9f67b7115cb8ea15ca",
  "feePayerSignatures": [
    {
      "V": "0x25",
      "R": "0x1c7de2c83542b623ba47722f310c0e5893486eef4eed70b634d456262fb430a7",
      "S": "0x177929c52669c4b9433565a76e53723b702bae8142debe1981062f59f25062ab"
    }
  ],
  "from": "0x0fcda0f2efbe1b4e61b487701ce4f2f8abc3723d",
  "gas": "0x174876e800",
  "gasPrice": "0x0",
  "gasUsed": "0xb0bc",
  "input": "0x6353586b0000000000000000000000000fcda0f2efbe1b4e61b487701ce4f2f8abc3723d",
  "logs": [],
  "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "nonce": "0xe",
  "senderTxHash": "0xffd354e4e271ff94a7459c2f1bc0df20dc112a83f5625ff7e31d196444f72710",
  "signatures": [
    {
      "V": "0x25",
      "R": "0xefc6fec3dae47a08941712f637c95dbc46ef2afd3d16e68da602a878c0bba047",
      "S": "0x938a5374edcea0503df8e7af906a7642f7e935eab7c489b7ca8b976a8e5ab7e"
    }
  ],
  "status": "0x1",
  "to": "0x636f6e74726163742e6b6c6179746e0000000000",
  "transactionHash": "0x658a118112ffb0c06adecd59b0f11b58cf7d8afd7ec5e5d323cfca021c3dcb37",
  "transactionIndex": "0x7",
  "type": "TxTypeFeeDelegatedSmartContractExecution",
  "typeInt": 49,
  "value": "0xa"
}
```

## TxTypeFeeDelegatedAccountUpdate <a href="#txtypefeedelegatedaccountupdate" id="txtypefeedelegatedaccountupdate"></a>

TxTypeFeeDelegatedAccountUpdate는 해당 계정의 키를 업데이트합니다. 트랜잭션 수수료는 트랜잭션 수수료 납부자가 지불합니다. 이 트랜잭션 유형은 다음과 같은 변경 사항을 만듭니다.

1. The fee payer's balance decreases by the amount of the transaction fee.
2. The sender's nonce increases by one.
3. The account's key is updated with `key`.
4. Once this type of transaction is executed, transactions sent from the account afterward will be validated with the new `key`.
5. The transaction fee is paid by the fee payer.

### Attributes <a href="#attributes" id="attributes"></a>

| Attribute          | Type                                      | Description                                                                                                                                                                                                                                                                                                                      |
| ------------------ | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| type               | uint8 (Go)                                | The type of TxTypeAccountUpdate. 이는 0x21이어야 합니다.                                                                                                                                                                                                                                                                                 |
| nonce              | uint64 (Go)                               | A value used to uniquely identify a sender’s transaction. If two transactions with the same nonce are generated by a sender, only one is executed.                                                                                                                                                                               |
| gasPrice           | \*big.Int (Go)                            | A multiplier to get how much the sender will pay in tokens. The amount of tokens the sender will pay is calculated via `gas` \* `gasPrice`. For example, the sender will pay 10 KLAY for a transaction fee if gas is 10 and gasPrice is 10^18. See [Unit of KLAY](/content/klaytn/design/klaytn-native-coin-klay#units-of-klay). |
| gas                | uint64 (Go)                               | The maximum amount of transaction fee the transaction is allowed to use.                                                                                                                                                                                                                                                         |
| from               | common.Address (Go)                       | The address of the sender. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                               |
| key                | AccountKey (Go)                           | [AccountKey](/content/klaytn/design/accounts#account-key) to be updated to the account.                                                                                                                                                                                                                                          |
| txSignatures       | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The sender's signatures. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                 |
| feePayer           | common.Address (Go)                       | The address of the fee payer.                                                                                                                                                                                                                                                                                                    |
| feePayerSignatures | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The fee payer's signatures.                                                                                                                                                                                                                                                                                                      |

### RLP Encoding for Signature of the Sender <a href="#rlp-encoding-for-signature-of-the-sender" id="rlp-encoding-for-signature-of-the-sender"></a>

To make a signature of the sender, RLP serialization should be done like the following:

```javascript
SigRLP = encode([encode([type, nonce, gasPrice, gas, from, rlpEncodedKey]), chainid, 0, 0])`
SigHash = keccak256(SigRLP)
Signature = sign(SigHash, <the sender's private key>)
```

### RLP Encoding for Signature of the Fee Payer <a href="#rlp-encoding-for-signature-of-the-fee-payer" id="rlp-encoding-for-signature-of-the-fee-payer"></a>

To make a signature of the fee payer, RLP serialization should be done like the following:

```javascript
SigFeePayerRLP = encode([encode([type, nonce, gasPrice, gas, from, rlpEncodedKey]), feePayer, chainid, 0, 0])
SigFeePayerHash = keccak256(SigFeePayerRLP)
SignatureFeePayer = sign(SigFeePayerHash, <the fee payer's private key>)
```

### RLP Encoding for SenderTxHash <a href="#rlp-encoding-for-sendertxhash" id="rlp-encoding-for-sendertxhash"></a>

To make a SenderTxHash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
SenderTxHashRLP = type + encode([nonce, gasPrice, gas, from, rlpEncodedKey, txSignatures])
SenderTxHash = keccak256(SenderTxHashRLP)
```

### RLP Encoding for Transaction Hash <a href="#rlp-encoding-for-transaction-hash" id="rlp-encoding-for-transaction-hash"></a>

To make a transaction hash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
feePayerSignatures (a single signature) = [[v, r, s]]
feePayerSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
TxHashRLP = type + encode([nonce, gasPrice, gas, from, rlpEncodedKey, txSignatures, feePayer, feePayerSignatures])
TxHash = keccak256(TxHashRLP)
```

### RLP Encoding (Example) <a href="#rlp-encoding-example" id="rlp-encoding-example"></a>

The following shows the result of RLP serialization and the transaction object:

```javascript
ChainID 0x1
PrivateKey 0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8
PublicKey.X 0x3a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d
PublicKey.Y 0x8072e77939dc03ba44790779b7a1025baf3003f6732430e20cd9b76d953391b3
SigRLP 0xf849b844f842218204d219830f424094a94f5374fce5edbc8e2a8697c15331677e6ebf0ba302a1033a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d018080
SigHash 0x78437953e6beb985ea3ccbee8d6a648a09d11249389477a32c7094fc7b8765ef
Signature f845f84326a0ab69d9adca15d9763c4ce6f98b35256717c6e932007658f19c5a255de9e70ddaa026aa676a3a1a6e96aff4a3df2335788d614d54fb4db1c3c48551ce1fa7ac5e52
FeePayerPrivateKey 0xb9d5558443585bca6f225b935950e3f6e69f9da8a5809a83f51c3365dff53936
FeePayerPublicKey.X 0x327434d4cfc66ef8857d431419e9deebdc53a3e415edcc55382e2d417b8dd102
FeePayerPublicKey.Y 0x65fc97045707faf7b8f81ac65089d4cc71f69ad0bf1bc8559bc24f13fc284ced
SigRLPFeePayer 0xf85eb844f842218204d219830f424094a94f5374fce5edbc8e2a8697c15331677e6ebf0ba302a1033a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d945a0043070275d9f6054307ee7348bd660849d90f018080
SigHashFeePayer 0x1026d3ac74f56b52453d656b084d06798479b8bcfda1868d8beaa23e36f3aeb3
SignatureFeePayer f845f84326a0f295cd69b4144d9dbc906ba144933d2cc535d9d559f7a92b4672cc5485bf3a60a0784b8060234ffd64739b5fc2f2503939340ab4248feaa6efcf62cb874345fe40
TxHashRLP 0x21f8e48204d219830f424094a94f5374fce5edbc8e2a8697c15331677e6ebf0ba302a1033a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33df845f84326a0ab69d9adca15d9763c4ce6f98b35256717c6e932007658f19c5a255de9e70ddaa026aa676a3a1a6e96aff4a3df2335788d614d54fb4db1c3c48551ce1fa7ac5e52945a0043070275d9f6054307ee7348bd660849d90ff845f84326a0f295cd69b4144d9dbc906ba144933d2cc535d9d559f7a92b4672cc5485bf3a60a0784b8060234ffd64739b5fc2f2503939340ab4248feaa6efcf62cb874345fe40
TxHash 756ff5d3912a4089659614d42a218eee59e602a5992bddca383c2d295c6637bb
SenderTxHashRLP 0x21f8888204d219830f424094a94f5374fce5edbc8e2a8697c15331677e6ebf0ba302a1033a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33df845f84326a0ab69d9adca15d9763c4ce6f98b35256717c6e932007658f19c5a255de9e70ddaa026aa676a3a1a6e96aff4a3df2335788d614d54fb4db1c3c48551ce1fa7ac5e52
SenderTxHash f56937017bd3b75c637ba5b4ce90df20c166006a2a529b42e808bc806159b98f

    TX(756ff5d3912a4089659614d42a218eee59e602a5992bddca383c2d295c6637bb)
    Type:          TxTypeFeeDelegatedAccountUpdate
    From:          0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B
    Nonce:         1234
    GasPrice:      0x19
    GasLimit:      0xf4240
    Key:           AccountKeyPublic: S256Pubkey:{"x":"0x3a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d","y":"0x8072e77939dc03ba44790779b7a1025baf3003f6732430e20cd9b76d953391b3"}
    Signature:     [{"V":"0x26","R":"0xab69d9adca15d9763c4ce6f98b35256717c6e932007658f19c5a255de9e70dda","S":"0x26aa676a3a1a6e96aff4a3df2335788d614d54fb4db1c3c48551ce1fa7ac5e52"}]
    FeePayer:      0x5A0043070275d9f6054307Ee7348bD660849D90f
    FeePayerSig:   [{"V":"0x26","R":"0xf295cd69b4144d9dbc906ba144933d2cc535d9d559f7a92b4672cc5485bf3a60","S":"0x784b8060234ffd64739b5fc2f2503939340ab4248feaa6efcf62cb874345fe40"}]
    Hex:           21f8e48204d219830f424094a94f5374fce5edbc8e2a8697c15331677e6ebf0ba302a1033a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33df845f84326a0ab69d9adca15d9763c4ce6f98b35256717c6e932007658f19c5a255de9e70ddaa026aa676a3a1a6e96aff4a3df2335788d614d54fb4db1c3c48551ce1fa7ac5e52945a0043070275d9f6054307ee7348bd660849d90ff845f84326a0f295cd69b4144d9dbc906ba144933d2cc535d9d559f7a92b4672cc5485bf3a60a0784b8060234ffd64739b5fc2f2503939340ab4248feaa6efcf62cb874345fe40
```

### RPC Output (Example) <a href="#rpc-output-example" id="rpc-output-example"></a>

The following shows a transaction object returned via JSON RPC.

```javascript
{
  "blockHash": "0x82983fe294d286e76486760e6904369285554e1744af16786c2393a956fb4ec4",
  "blockNumber": "0x2",
  "contractAddress": null,
  "feePayer": "0x0fcda0f2efbe1b4e61b487701ce4f2f8abc3723d",
  "feePayerSignatures": [
    {
      "V": "0x25",
      "R": "0x3b019642e5ae37f3ecbf85e6fc1ee77e51d1618299367bcedd816d0da6afb1e0",
      "S": "0x5c12c87811a74183f8b56b707fa90a916b1c641652c93e52300f5cee36141d73"
    }
  ],
  "from": "0x636f6c696e322e6b6c6179746e00000000000000",
  "gas": "0x174876e800",
  "gasPrice": "0x5d21dba00",
  "gasUsed": "0xc738",
  "key": "0x02a1034ef27ba4b7d1ae09b166744c5b7ee4a7a0cc5c76b2e5d74523a0a4fb56db3191",
  "logs": [],
  "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "nonce": "0x0",
  "senderTxHash": "0xf4e7ef082451d4a3c8ad7c4348fc99c965a9c130bfc98d7971f3103e3dcfda3c",
  "signatures": [
    {
      "V": "0x26",
      "R": "0xd4cb16abcdf92969dc45efacaa5827ad55738fbda08a3dbaf0f0553643084a6",
      "S": "0x23f8055933b416cf15568a017e0a11e0a5c0a8f65477f6ec71de0bf837f4a681"
    }
  ],
  "status": "0x1",
  "transactionHash": "0xeb0c14d903db38deee116ac8a0d620e6ca6aa79e4f91393abbddfa30810b9d43",
  "transactionIndex": "0x2",
  "type": "TxTypeFeeDelegatedAccountUpdate",
  "typeInt": 33
},
```

## TxTypeFeeDelegatedCancel <a href="#txtypefeedelegatedcancel" id="txtypefeedelegatedcancel"></a>

TxTypeFeeDelegatedCancel는 트랜잭션 풀에서 같은 논스를 가진 트랜잭션을 취소합니다. 자세한 내용은 [TxTypeCancel](/content/klaytn/design/transactions/basic#txtypecancel)를 참조하세요.

The following changes will apply by this transaction type. 1. The fee payer's balance decreases by the amount of the transaction fee. 2. The sender's nonce increases by one.

### Attributes <a href="#attributes" id="attributes"></a>

| Attribute          | Type                                      | Description                                                                                                                                                                                                                                                                                                                                        |
| ------------------ | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| type               | uint8 (Go)                                | The type of TxTypeCancel. 이는 0x39이어야 합니다.                                                                                                                                                                                                                                                                                                          |
| nonce              | uint64 (Go)                               | A value used to uniquely identify a sender’s transaction. If two transactions with the same nonce are generated by a sender, only one is executed.                                                                                                                                                                                                 |
| gasPrice           | \*big.Int (Go)                            | A unit price of gas in `peb` the sender will pay for a transaction fee. The amount of transaction fee is calculated as `gas` \* `gasPrice`. For example, if the transaction consumes 10 units of gas and gasPrice is 10^18, the transaction fee will be 10 KLAY. See [Unit of KLAY](/content/klaytn/design/klaytn-native-coin-klay#units-of-klay). |
| gas                | uint64 (Go)                               | The maximum amount of transaction fee the transaction is allowed to use.                                                                                                                                                                                                                                                                           |
| from               | common.Address (Go)                       | The address of the sender. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                 |
| txSignatures       | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The sender's signatures. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                   |
| feePayer           | common.Address (Go)                       | The address of the fee payer.                                                                                                                                                                                                                                                                                                                      |
| feePayerSignatures | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The fee payer's signatures.                                                                                                                                                                                                                                                                                                                        |

### RLP Encoding for Signature of the Sender <a href="#rlp-encoding-for-signature-of-the-sender" id="rlp-encoding-for-signature-of-the-sender"></a>

To make a signature of the sender, RLP serialization should be done like the following:

```javascript
SigRLP = encode([encode([type, nonce, gasPrice, gas, from]), chainid, 0, 0])
SigHash = keccak256(SigRLP)
Signature = sign(SigHash, <the sender's private key>)
```

### RLP Encoding for Signature of the Fee Payer <a href="#rlp-encoding-for-signature-of-the-fee-payer" id="rlp-encoding-for-signature-of-the-fee-payer"></a>

To make a signature of the fee payer, RLP serialization should be done like the following:

```javascript
SigFeePayerRLP = encode([encode([type, nonce, gasPrice, gas, from]), feePayer, chainid, 0, 0])
SigFeePayerHash = keccak256(SigFeePayerRLP)
SignatureFeePayer = sign(SigFeePayerHash, <the fee payer's private key>)
```

### RLP Encoding for SenderTxHash <a href="#rlp-encoding-for-sendertxhash" id="rlp-encoding-for-sendertxhash"></a>

To make a SenderTxHash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
SenderTxHashRLP = type + encode([nonce, gasPrice, gas, from, txSignatures])
SenderTxHash = keccak256(SenderTxHashRLP)
```

### RLP Encoding for Transaction Hash <a href="#rlp-encoding-for-transaction-hash" id="rlp-encoding-for-transaction-hash"></a>

To make a transaction hash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
feePayerSignatures (a single signature) = [[v, r, s]]
feePayerSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
TxHashRLP = type + encode([nonce, gasPrice, gas, from, txSignatures, feePayer, feePayerSignatures])
TxHash = keccak256(TxHashRLP)
```

### RLP Encoding (Example) <a href="#rlp-encoding-example" id="rlp-encoding-example"></a>

The following shows the result of RLP serialization and the transaction object:

```javascript
ChainID 0x1
PrivateKey 0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8
PublicKey.X 0x3a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d
PublicKey.Y 0x8072e77939dc03ba44790779b7a1025baf3003f6732430e20cd9b76d953391b3
SigRLP 0xe39fde398204d219830f424094a94f5374fce5edbc8e2a8697c15331677e6ebf0b018080
SigHash 0xd36c4277f4aa1d483a5fc4d656aeea50416c28adddb27a234d320290bd2a343c
Signature f845f84326a08409f5441d4725f90905ad87f03793857d124de7a43169bc67320cd2f020efa9a060af63e87bdc565d7f7de906916b2334336ee7b24d9a71c9521a67df02e7ec92
FeePayerPrivateKey 0xb9d5558443585bca6f225b935950e3f6e69f9da8a5809a83f51c3365dff53936
FeePayerPublicKey.X 0x327434d4cfc66ef8857d431419e9deebdc53a3e415edcc55382e2d417b8dd102
FeePayerPublicKey.Y 0x65fc97045707faf7b8f81ac65089d4cc71f69ad0bf1bc8559bc24f13fc284ced
SigRLPFeePayer 0xf8389fde398204d219830f424094a94f5374fce5edbc8e2a8697c15331677e6ebf0b945a0043070275d9f6054307ee7348bd660849d90f018080
SigHashFeePayer 0x15859ecc06acbd2dd5820c5968a85590826d1f6affb938e89559558ac4f86a24
SignatureFeePayer f845f84326a0044d5b25e8c649a1fdaa409dc3817be390ad90a17c25bc17c89b6d5d248495e0a073938e690d27b5267c73108352cf12d01de7fd0077b388e94721aa1fa32f85ec
TxHashRLP 0x39f8c08204d219830f424094a94f5374fce5edbc8e2a8697c15331677e6ebf0bf845f84326a08409f5441d4725f90905ad87f03793857d124de7a43169bc67320cd2f020efa9a060af63e87bdc565d7f7de906916b2334336ee7b24d9a71c9521a67df02e7ec92945a0043070275d9f6054307ee7348bd660849d90ff845f84326a0044d5b25e8c649a1fdaa409dc3817be390ad90a17c25bc17c89b6d5d248495e0a073938e690d27b5267c73108352cf12d01de7fd0077b388e94721aa1fa32f85ec
TxHash 96b39d3ab849127d31a5f7b5c882ca9ba408cd9d875052640d51a64f8c4acbb2
SenderTxHashRLP 0x39f8648204d219830f424094a94f5374fce5edbc8e2a8697c15331677e6ebf0bf845f84326a08409f5441d4725f90905ad87f03793857d124de7a43169bc67320cd2f020efa9a060af63e87bdc565d7f7de906916b2334336ee7b24d9a71c9521a67df02e7ec92
SenderTxHash cc6c2673398903b3d906a3023b41636fc08bd1bddd5aa1602116091638f48447

    TX(96b39d3ab849127d31a5f7b5c882ca9ba408cd9d875052640d51a64f8c4acbb2)
    Type:          TxTypeFeeDelegatedCancel
    From:          0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B
    Nonce:         1234
    GasPrice:      0x19
    GasLimit:      0xf4240
    Signature:     [{"V":"0x26","R":"0x8409f5441d4725f90905ad87f03793857d124de7a43169bc67320cd2f020efa9","S":"0x60af63e87bdc565d7f7de906916b2334336ee7b24d9a71c9521a67df02e7ec92"}]
    FeePayer:      0x5A0043070275d9f6054307Ee7348bD660849D90f
    FeePayerSig:   [{"V":"0x26","R":"0x44d5b25e8c649a1fdaa409dc3817be390ad90a17c25bc17c89b6d5d248495e0","S":"0x73938e690d27b5267c73108352cf12d01de7fd0077b388e94721aa1fa32f85ec"}]
    Hex:           39f8c08204d219830f424094a94f5374fce5edbc8e2a8697c15331677e6ebf0bf845f84326a08409f5441d4725f90905ad87f03793857d124de7a43169bc67320cd2f020efa9a060af63e87bdc565d7f7de906916b2334336ee7b24d9a71c9521a67df02e7ec92945a0043070275d9f6054307ee7348bd660849d90ff845f84326a0044d5b25e8c649a1fdaa409dc3817be390ad90a17c25bc17c89b6d5d248495e0a073938e690d27b5267c73108352cf12d01de7fd0077b388e94721aa1fa32f85ec
```

### RPC Output (Example) <a href="#rpc-output-example" id="rpc-output-example"></a>

The following shows a transaction object returned via JSON RPC.

```javascript
{
  "blockHash": "0x82983fe294d286e76486760e6904369285554e1744af16786c2393a956fb4ec4",
  "blockNumber": "0x2",
  "contractAddress": null,
  "feePayer": "0x029fdce0457db02f05c4be9f67b7115cb8ea15ca",
  "feePayerSignatures": [
    {
      "V": "0x25",
      "R": "0x26a7c88e1fc77400f2a4c7911966a5e51b0873e3f26daf9d6519b93e3f3db6a3",
      "S": "0x560e5fa8d53ebf899eb48353bf14794c76784240a6a212f5ddbe7f1684088f3f"
    }
  ],
  "from": "0x0fcda0f2efbe1b4e61b487701ce4f2f8abc3723d",
  "gas": "0x174876e800",
  "gasPrice": "0x5d21dba00",
  "gasUsed": "0x7918",
  "logs": [],
  "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "nonce": "0x11",
  "senderTxHash": "0x2fea0ff37b8b936d4c06f29b98c4bd200827423fb445f931eb64725aefcda053",
  "signatures": [
    {
      "V": "0x26",
      "R": "0xcfdb5b3ff6c87a8f18ae606b371d1e569c56d35a737831b89052c5a8ef19d049",
      "S": "0x1ee63bd5a01c45d0c6f1b36a29e1c01b56baa719f008c556bc9054ac5a64bd8d"
    }
  ],
  "status": "0x1",
  "transactionHash": "0xf475e714b30aef0b79d46c9482289f3fbe51f1e44bcbc99a90ac8e25672bc969",
  "transactionIndex": "0xa",
  "type": "TxTypeFeeDelegatedCancel",
  "typeInt": 57
}
```

## TxTypeFeeDelegatedChainDataAnchoring <a href="#txtypefeedelegatedchaindataanchoring" id="txtypefeedelegatedchaindataanchoring"></a>

TxTypeFeeDelegatedChainDataAnchoring는 서비스체인 데이터를 Klaytn 메인체인에 앵커링하는 수수료 위임 트랜잭션입니다. Service chains periodically send this type of transaction to the Klaytn mainchain to ensure its security and credibility of data. For more details about the data anchoring, see [Anchoring](/content/installation-guide/deployment/service-chain/references/anchoring). 이 트랜잭션은 수수료 위임 트랜잭션이므로 트랜잭션 수수료가 트랜잭션 수수료 납부자에게 부과됩니다. Be mindful that it is not allowed to send this transaction via RPC. Currently, this transaction is executed through private p2p channels for security reasons. This transaction does not change the state of the Klaytn blockchain except the sender's nonce being increased by one.

### Attributes <a href="#attributes" id="attributes"></a>

| Attribute          | Type                                      | Description                                                                                                                                                                                                                                                                                                                                        |
| ------------------ | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| type               | uint8 (Go)                                | TxTypeFeeDelegatedChainDataAnchoring의 타입입니다. 이는 0x49이어야 합니다.                                                                                                                                                                                                                                                                                       |
| nonce              | uint64 (Go)                               | A value used to uniquely identify a sender’s transaction. If two transactions with the same nonce are generated by a sender, only one is executed.                                                                                                                                                                                                 |
| gasPrice           | \*big.Int (Go)                            | A unit price of gas in `peb` the sender will pay for a transaction fee. The amount of transaction fee is calculated as `gas` \* `gasPrice`. For example, if the transaction consumes 10 units of gas and gasPrice is 10^18, the transaction fee will be 10 KLAY. See [Unit of KLAY](/content/klaytn/design/klaytn-native-coin-klay#units-of-klay). |
| gas                | uint64 (Go)                               | The maximum amount of transaction fee the transaction is allowed to use.                                                                                                                                                                                                                                                                           |
| from               | common.Address (Go)                       | The address of the sender. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                 |
| input              | \[]byte (Go)                              | Data of the service chain.                                                                                                                                                                                                                                                                                                                         |
| txSignatures       | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The sender's signatures. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                   |
| feePayer           | common.Address (Go)                       | The address of the fee payer.                                                                                                                                                                                                                                                                                                                      |
| feePayerSignatures | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The fee payer's signatures.                                                                                                                                                                                                                                                                                                                        |

### RLP Encoding for Signature of the Sender <a href="#rlp-encoding-for-signature-of-the-sender" id="rlp-encoding-for-signature-of-the-sender"></a>

To make a signature of the sender, RLP serialization should be done like the following:

```javascript
SigRLP = encode([encode([type, nonce, gasPrice, gas, from, anchoredData]), chainid, 0, 0])
SigHash = keccak256(SigRLP)
Signature = sign(SigHash, <private key>)
```

### RLP Encoding for Signature of the Fee Payer <a href="#rlp-encoding-for-signature-of-the-fee-payer" id="rlp-encoding-for-signature-of-the-fee-payer"></a>

To make a signature of the fee payer, RLP serialization should be done like the following:

```javascript
SigFeePayerRLP = encode([encode([type, nonce, gasPrice, gas, from, anchoredData]), feePayer, chainid, 0, 0])
SigFeePayerHash = keccak256(SigFeePayerRLP)
SignatureFeePayer = sign(SigFeePayerHash, <the fee payer's private key>)
```

### RLP Encoding for SenderTxHash <a href="#rlp-encoding-for-sendertxhash" id="rlp-encoding-for-sendertxhash"></a>

To make a SenderTxHash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
SenderTxHashRLP = type + encode([nonce, gasPrice, gas, from, anchoredData, txSignatures])
SenderTxHash = keccak256(SenderTxHashRLP)
```

### RLP Encoding for Transaction Hash <a href="#rlp-encoding-for-transaction-hash" id="rlp-encoding-for-transaction-hash"></a>

To make a transaction hash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
feePayerSignatures (a single signature) = [[v, r, s]]
feePayerSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
TxHashRLP = type + encode([nonce, gasPrice, gas, from, anchoredData, txSignatures, feePayer, feePayerSignatures])
TxHash = keccak256(TxHashRLP)
```

### RLP Encoding (Example) <a href="#rlp-encoding-example" id="rlp-encoding-example"></a>

The following shows the result of RLP serialization and the transaction object:

```javascript
ChainID 0x01
PrivateKey 0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8
PublicKey.X 0x3a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d
PublicKey.Y 0x8072e77939dc03ba44790779b7a1025baf3003f6732430e20cd9b76d953391b3
SigRLP 0xf8dbb8d6f8d449118505d21dba0085174876e80094a94f5374fce5edbc8e2a8697c15331677e6ebf0bb8aff8ad80b8aaf8a8a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000004058006018080
SigHash 0x92e385b4a162170ee87b2b2e598f686b1d16f385d98ad626147305624abec0b3
Signature 0xf845f84326a0afe41edc9cce1185ab9065ca7dbfb89ab5c7bde3602a659aa258324124644142a0317848698248ba7cc057b8f0dd19a27b52ef904d29cb72823100f1ed18ba2bb3
FeePayerPublicKey.X 0x327434d4cfc66ef8857d431419e9deebdc53a3e415edcc55382e2d417b8dd102
FeePayerPublicKey.Y 0x65fc97045707faf7b8f81ac65089d4cc71f69ad0bf1bc8559bc24f13fc284ced
SigRLPFeePayer 0xf8f0b8d6f8d449118505d21dba0085174876e80094a94f5374fce5edbc8e2a8697c15331677e6ebf0bb8aff8ad80b8aaf8a8a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000000040580069433f524631e573329a550296f595c820d6c65213f018080
SigHashFeePayer 0x4d58fdf276fde1e221b6bab8c6621ae1639b00a7a70d2bd0a114001692a3a7d1
SignatureFeePayer 0xf845f84325a0309e46db21a1bf7bfdae24d9192aca69516d6a341ecce8971fc69cff481cee76a04b939bf7384c4f919880307323a5e36d4d6e029bae1887a43332710cdd48f174
TxHashRLP 0x49f90176118505d21dba0085174876e80094a94f5374fce5edbc8e2a8697c15331677e6ebf0bb8aff8ad80b8aaf8a8a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000004058006f845f84326a0afe41edc9cce1185ab9065ca7dbfb89ab5c7bde3602a659aa258324124644142a0317848698248ba7cc057b8f0dd19a27b52ef904d29cb72823100f1ed18ba2bb39433f524631e573329a550296f595c820d6c65213ff845f84325a0309e46db21a1bf7bfdae24d9192aca69516d6a341ecce8971fc69cff481cee76a04b939bf7384c4f919880307323a5e36d4d6e029bae1887a43332710cdd48f174
TxHash 0xecf1ec12937065617f9b3cd07570452bfdb75dc36404c4f37f78995c6dc462af
SenderTxHashRLP 0x49f9011a118505d21dba0085174876e80094a94f5374fce5edbc8e2a8697c15331677e6ebf0bb8aff8ad80b8aaf8a8a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000004058006f845f84326a0afe41edc9cce1185ab9065ca7dbfb89ab5c7bde3602a659aa258324124644142a0317848698248ba7cc057b8f0dd19a27b52ef904d29cb72823100f1ed18ba2bb3
SenderTxHash 0x4f5c00ea8f6346baa7d4400dfefd72efa5ec219561ebcebed7be8a2b79d52bcd

    TX(ecf1ec12937065617f9b3cd07570452bfdb75dc36404c4f37f78995c6dc462af)
    Type:          TxTypeFeeDelegatedChainDataAnchoring
    From:          0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B
    Nonce:         17
    GasPrice:      0x5d21dba00
    GasLimit:      0x174876e800
    AnchoredData:  f8ad80b8aaf8a8a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000004058006
    Signature:     [{"V":"0x26","R":"0xafe41edc9cce1185ab9065ca7dbfb89ab5c7bde3602a659aa258324124644142","S":"0x317848698248ba7cc057b8f0dd19a27b52ef904d29cb72823100f1ed18ba2bb3"}]
    FeePayer:      0x33f524631e573329a550296F595c820D6c65213f
    FeePayerSig:   [{"V":"0x25","R":"0x309e46db21a1bf7bfdae24d9192aca69516d6a341ecce8971fc69cff481cee76","S":"0x4b939bf7384c4f919880307323a5e36d4d6e029bae1887a43332710cdd48f174"}]
    Hex:           49f90176118505d21dba0085174876e80094a94f5374fce5edbc8e2a8697c15331677e6ebf0bb8aff8ad80b8aaf8a8a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000004058006f845f84326a0afe41edc9cce1185ab9065ca7dbfb89ab5c7bde3602a659aa258324124644142a0317848698248ba7cc057b8f0dd19a27b52ef904d29cb72823100f1ed18ba2bb39433f524631e573329a550296f595c820d6c65213ff845f84325a0309e46db21a1bf7bfdae24d9192aca69516d6a341ecce8971fc69cff481cee76a04b939bf7384c4f919880307323a5e36d4d6e029bae1887a43332710cdd48f174
```

### RPC Output (Example) <a href="#rpc-output-example" id="rpc-output-example"></a>

The following shows a transaction object returned via JSON RPC.

```javascript
{
    "blockHash": "0x170a32e16b6fdced144d5104f5aecf753878bd9f1a7d87ddccc2e6d2ba27354c",
    "blockNumber": "0x2",
    "contractAddress": null,
    "feePayer": "0x33f524631e573329a550296f595c820d6c65213f",
    "feePayerSignatures": [
        {
            "V": "0x25",
            "R": "0x309e46db21a1bf7bfdae24d9192aca69516d6a341ecce8971fc69cff481cee76",
            "S": "0x4b939bf7384c4f919880307323a5e36d4d6e029bae1887a43332710cdd48f174"
        }
    ],
    "from": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
    "gas": "0x174876e800",
    "gasPrice": "0x5d21dba00",
    "gasUsed": "0xbd74",
    "input": "0xf8ad80b8aaf8a8a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000004058006",
    "logs": [],
    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "nonce": "0x11",
    "senderTxHash": "0x4f5c00ea8f6346baa7d4400dfefd72efa5ec219561ebcebed7be8a2b79d52bcd",
    "signatures": [
        {
            "V": "0x26",
            "R": "0xafe41edc9cce1185ab9065ca7dbfb89ab5c7bde3602a659aa258324124644142",
            "S": "0x317848698248ba7cc057b8f0dd19a27b52ef904d29cb72823100f1ed18ba2bb3"
        }
    ],
    "status": "0x1",
    "transactionHash": "0xecf1ec12937065617f9b3cd07570452bfdb75dc36404c4f37f78995c6dc462af",
    "transactionIndex": "0xa",
    "type": "TxTypeFeeDelegatedChainDataAnchoring",
    "typeInt": 73
}
```


# 수수료 부분 위임 트랜잭션

## TxTypeFeeDelegatedValueTransferWithRatio <a href="#txtypefeedelegatedvaluetransferwithratio" id="txtypefeedelegatedvaluetransferwithratio"></a>

TxTypeFeeDelegatedValueTransferWithRatio는 사용자가 KLAY를 보내려고 할 때 사용됩니다. Klaytn은 각 목적에 맞는 여러가지 트랜잭션 유형들을 제공하는데, TxTypeFeeDelegatedValueTransferWithRatio는 KLAY를 EOA에 전송할 때 사용하는 기능입니다. 따라서 TxTypeFeeDelegatedValueTransferWithRatio는 `to`가 EOA일때만 작동합니다. KLAY를 스마트 컨트랙트로 전송하려면 [TxTypeFeeDelegatedSmartContractExecutionWithRatio](#txtypefeedelegatedsmartcontractexecutionwithratio)를 대신 사용하여야 합니다. The following changes will be made by this transaction type.

1. 수수료 납부자의 잔고는 주어진 트랜잭션 수수료 비율(fee ratio)에 따라 감소합니다.
2. 발신자의 잔고는 남은 트랜잭션 수수료만큼 줄어듭니다. 예를 들어 만약 `feeRatio`가 30이라면 30%의 트랜잭션 수수료가 수수료 납부자에 의해서 지불되고, 남은 70%는 발신자에 의해서 지불됩니다.
3. The sender's nonce increases by one.
4. `value` KLAY is transferred from the sender to the recipient.

### Attributes <a href="#attributes" id="attributes"></a>

| Attribute          | Type                                      | Description                                                                                                                                                                                                                                                                                                                                        |
| ------------------ | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| type               | uint8 (Go)                                | TxTypeFeeDelegatedValueTransferWithRatio의 유형입니다. 이는 0x0a이어야 합니다.                                                                                                                                                                                                                                                                                   |
| nonce              | uint64 (Go)                               | A value used to uniquely identify a sender’s transaction. If two transactions with the same nonce are generated by a sender, only one is executed.                                                                                                                                                                                                 |
| gasPrice           | \*big.Int (Go)                            | A unit price of gas in `peb` the sender will pay for a transaction fee. The amount of transaction fee is calculated as `gas` \* `gasPrice`. For example, if the transaction consumes 10 units of gas and gasPrice is 10^18, the transaction fee will be 10 KLAY. See [Unit of KLAY](/content/klaytn/design/klaytn-native-coin-klay#units-of-klay). |
| gas                | uint64 (Go)                               | The maximum amount of gas the transaction is allowed to use.                                                                                                                                                                                                                                                                                       |
| to                 | common.Address (Go)                       | The account address that will receive the transferred value.                                                                                                                                                                                                                                                                                       |
| value              | \*big.Int (Go)                            | The amount of KLAY in `peb` to be transferred.                                                                                                                                                                                                                                                                                                     |
| from               | common.Address (Go)                       | The address of the sender. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                 |
| feeRatio           | uint8 (Go)                                | Fee ratio of the fee payer. 유효한 범위는 1에서 99 사이입니다. 영(0)은 허용되지 않습니다. 100 이상 또한 허용되지 않습니다.                                                                                                                                                                                                                                                            |
| txSignatures       | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The sender's signatures. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                   |
| feePayer           | common.Address (Go)                       | The address of the fee payer.                                                                                                                                                                                                                                                                                                                      |
| feePayerSignatures | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The fee payer's signatures.                                                                                                                                                                                                                                                                                                                        |

### RLP Encoding for Signature of the Sender <a href="#rlp-encoding-for-signature-of-the-sender" id="rlp-encoding-for-signature-of-the-sender"></a>

To make a signature of the sender, RLP serialization should be done like the following:

```javascript
SigRLP = encode([encode([type, nonce, gasPrice, gas, to, value, from, feeRatio]), chainid, 0, 0])
SigHash = keccak256(SigRLP)
Signature = sign(SigHash, <the sender's private key>)
```

### RLP Encoding for Signature of the Fee Payer <a href="#rlp-encoding-for-signature-of-the-fee-payer" id="rlp-encoding-for-signature-of-the-fee-payer"></a>

To make a signature of the fee payer, RLP serialization should be done like the following:

```javascript
SigFeePayerRLP = encode([encode([type, nonce, gasPrice, gas, to, value, from, feeRatio]), feePayer, chainid, 0, 0])
SigFeePayerHash = keccak256(SigFeePayerRLP)
SignatureFeePayer = sign(SigFeePayerHash, <the fee payer's private key>)
```

### RLP Encoding for SenderTxHash <a href="#rlp-encoding-for-sendertxhash" id="rlp-encoding-for-sendertxhash"></a>

To make a SenderTxHash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
SenderTxHashRLP = type + encode([nonce, gasPrice, gas, to, value, from, feeRatio, txSignatures])
SenderTxHash = keccak256(SenderTxHashRLP)
```

### RLP Encoding for Transaction Hash <a href="#rlp-encoding-for-transaction-hash" id="rlp-encoding-for-transaction-hash"></a>

To make a transaction hash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
feePayerSignatures (a single signature) = [[v, r, s]]
feePayerSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
TxHashRLP = type + encode([nonce, gasPrice, gas, to, value, from, feeRatio, txSignatures, feePayer, feePayerSignatures])
TxHash = keccak256(TxHashRLP)
```

### RLP Encoding (Example) <a href="#rlp-encoding-example" id="rlp-encoding-example"></a>

The following shows the result of RLP serialization and the transaction object:

```javascript
ChainID 0x1
PrivateKey 0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8
PublicKey.X 0x3a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d
PublicKey.Y 0x8072e77939dc03ba44790779b7a1025baf3003f6732430e20cd9b76d953391b3
SigRLP 0xf83ab6f50a8204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0b1e018080
SigHash 0x0f7d520cd00034299b36004c21b571263dbb9a77edbd5920c4136f7f74050d9d
Signature f845f84325a0dde32b8241f039a82b124fe94d3e556eb08f0d6f26d07dcc0f3fca621f1090caa01c8c336b358ab6d3a2bbf25de2adab4d01b754e2fb3b9b710069177d54c1e956
FeePayerPrivateKey 0xb9d5558443585bca6f225b935950e3f6e69f9da8a5809a83f51c3365dff53936
FeePayerPublicKey.X 0x327434d4cfc66ef8857d431419e9deebdc53a3e415edcc55382e2d417b8dd102
FeePayerPublicKey.Y 0x65fc97045707faf7b8f81ac65089d4cc71f69ad0bf1bc8559bc24f13fc284ced
SigRLPFeePayer 0xf84fb6f50a8204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0b1e945a0043070275d9f6054307ee7348bd660849d90f018080
SigHashFeePayer 0x38123c30a5f83db853e9ae4e8dd8d4f6aa6840415acffb8dbf18b2050463dec4
SignatureFeePayer f845f84326a0091ecf53f91bb97bb694f2f2443f3563ac2b646d651497774524394aae396360a044228b88f275aa1ec1bab43681d21dc7e3a676786ed1906f6841d0a1a188f88a
TxHashRLP 0x0af8d78204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0b1ef845f84325a0dde32b8241f039a82b124fe94d3e556eb08f0d6f26d07dcc0f3fca621f1090caa01c8c336b358ab6d3a2bbf25de2adab4d01b754e2fb3b9b710069177d54c1e956945a0043070275d9f6054307ee7348bd660849d90ff845f84326a0091ecf53f91bb97bb694f2f2443f3563ac2b646d651497774524394aae396360a044228b88f275aa1ec1bab43681d21dc7e3a676786ed1906f6841d0a1a188f88a
TxHash 83a89f4debd8e9d6374b987e25132b3a4030c9cf9ace2fc6e7d1086fcea2ce40
SenderTxHashRLP 0x0af87b8204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0b1ef845f84325a0dde32b8241f039a82b124fe94d3e556eb08f0d6f26d07dcc0f3fca621f1090caa01c8c336b358ab6d3a2bbf25de2adab4d01b754e2fb3b9b710069177d54c1e956
SenderTxHash 4711ed4023e821425968342c1d50063b6bc3176b1792b7075cfeee3656d450f6

    TX(83a89f4debd8e9d6374b987e25132b3a4030c9cf9ace2fc6e7d1086fcea2ce40)
    Type:          TxTypeFeeDelegatedValueTransferWithRatio
    From:          0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B
    To:            0x7b65B75d204aBed71587c9E519a89277766EE1d0
    Nonce:         1234
    GasPrice:      0x19
    GasLimit:      0xf4240
    Value:         0xa
    Signature:     [{"V":"0x25","R":"0xdde32b8241f039a82b124fe94d3e556eb08f0d6f26d07dcc0f3fca621f1090ca","S":"0x1c8c336b358ab6d3a2bbf25de2adab4d01b754e2fb3b9b710069177d54c1e956"}]
    FeePayer:      0x5A0043070275d9f6054307Ee7348bD660849D90f
    FeeRatio:      30
    FeePayerSig:   [{"V":"0x26","R":"0x91ecf53f91bb97bb694f2f2443f3563ac2b646d651497774524394aae396360","S":"0x44228b88f275aa1ec1bab43681d21dc7e3a676786ed1906f6841d0a1a188f88a"}]
    Hex:           0af8d78204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0b1ef845f84325a0dde32b8241f039a82b124fe94d3e556eb08f0d6f26d07dcc0f3fca621f1090caa01c8c336b358ab6d3a2bbf25de2adab4d01b754e2fb3b9b710069177d54c1e956945a0043070275d9f6054307ee7348bd660849d90ff845f84326a0091ecf53f91bb97bb694f2f2443f3563ac2b646d651497774524394aae396360a044228b88f275aa1ec1bab43681d21dc7e3a676786ed1906f6841d0a1a188f88a
```

### RPC Output (Example) <a href="#rpc-output-example" id="rpc-output-example"></a>

The following shows a transaction object returned via JSON RPC.

```javascript
{
  "blockHash": "0x7ad6ed1f9955be00db8fb5452125f0e9a3c0856abb5b4cc4aed91ffc134321da",
  "blockNumber": "0x1",
  "contractAddress": null,
  "feePayer": "0x029fdce0457db02f05c4be9f67b7115cb8ea15ca",
  "feePayerSignatures": [
    {
      "V": "0x25",
      "R": "0xb8583f638efefb297922aa8b8a30cf451a30e266126d52da03ba9ead0fbb1ccd",
      "S": "0x4bc5ca3756f88d857d115b128b00babe5b3c0b089f087a0b30a9ced269e00603"
    }
  ],
  "feeRatio": "0x14",
  "from": "0x0fcda0f2efbe1b4e61b487701ce4f2f8abc3723d",
  "gas": "0x174876e800",
  "gasPrice": "0x5d21dba00",
  "gasUsed": "0x8ca0",
  "logs": [],
  "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "nonce": "0x3",
  "senderTxHash": "0xac372c68d2937383d4344a2d187e70b207c76160eb407b68e08c944b919328de",
  "signatures": [
    {
      "V": "0x26",
      "R": "0x1a8d5bf583843ceba87943569a34a8a6caa18a9ab5e4cf6914d8048e607787bc",
      "S": "0x27458275c84adcb8144b4596946111f1a539643941de74f587fa69a7df98ed1b"
    }
  ],
  "status": "0x1",
  "to": "0x75c3098be5e4b63fbac05838daaee378dd48098d",
  "transactionHash": "0x670ff613022278cc2551a7e4669d8911f1658ffaa4dcc3695b14f39194a8a38c",
  "transactionIndex": "0x3",
  "type": "TxTypeFeeDelegatedValueTransferWithRatio",
  "typeInt": 10,
  "value": "0x989680"
}
```

## TxTypeFeeDelegatedValueTransferMemoWithRatio <a href="#txtypefeedelegatedvaluetransfermemowithratio" id="txtypefeedelegatedvaluetransfermemowithratio"></a>

TxTypeFeeDelegatedValueTransferMemoWithRatio는 사용자가 특정 메시지와 함께 KLAY를 보내려고 할 때 사용됩니다. 따라서 TxTypeFeeDelegatedValueTransferMemoWithRatio는 `to`가 EOA일때만 작동합니다. To transfer KLAY to a smart contract account, use [TxTypeFeeDelegatedSmartContractExecutionWithRatio](#txtypefeedelegatedsmartcontractexecutionwithratio) instead. The following changes will be made by this transaction type.

1. 트랜잭션 수수료 납부자의 잔액은 트랜잭션 수수료의 수수료 부담 비율만큼 감소합니다.
2. The sender's balance decreases by the remaining transaction fee. 예를 들어 만약 `feeRatio`가 30이라면 30%의 트랜잭션 수수료가 수수료 납부자에 의해서 지불되고, 남은 70%는 발신자에 의해서 지불됩니다.
3. The sender's nonce increases by one.
4. `value` KLAY is transferred from the sender to the recipient.

### Attributes <a href="#attributes" id="attributes"></a>

| Attribute          | Description                               | Type                                                                                                                                                                                                                                                                                                                                               |
| ------------------ | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| type               | uint8 (Go)                                | TxTypeFeeDelegatedValueTransferMemoWithRatio의 유형입니다. 이는 0x12이어야 합니다                                                                                                                                                                                                                                                                                |
| nonce              | uint64 (Go)                               | A value used to uniquely identify a sender’s transaction. If two transactions with the same nonce are generated by a sender, only one is executed.                                                                                                                                                                                                 |
| gasPrice           | \*big.Int (Go)                            | A unit price of gas in `peb` the sender will pay for a transaction fee. The amount of transaction fee is calculated as `gas` \* `gasPrice`. For example, if the transaction consumes 10 units of gas and gasPrice is 10^18, the transaction fee will be 10 KLAY. See [Unit of KLAY](/content/klaytn/design/klaytn-native-coin-klay#units-of-klay). |
| gas                | uint64 (Go)                               | The maximum amount of gas the transaction is allowed to use.                                                                                                                                                                                                                                                                                       |
| to                 | common.Address (Go)                       | The account address that will receive the transferred value.                                                                                                                                                                                                                                                                                       |
| value              | \*big.Int (Go)                            | The amount of KLAY in `peb` to be transferred.                                                                                                                                                                                                                                                                                                     |
| from               | common.Address (Go)                       | The address of the sender. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                 |
| input              | \[]byte (Go)                              | Data attached to the transaction. The message should be passed to this attribute.                                                                                                                                                                                                                                                                  |
| feeRatio           | uint8 (Go)                                | Fee ratio of the fee payer. The valid range is between 1 and 99. Zero(0) is not allowed. 100 and above are not allowed as well.                                                                                                                                                                                                                    |
| txSignatures       | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The sender's signatures. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                   |
| feePayer           | common.Address (Go)                       | The address of the fee payer.                                                                                                                                                                                                                                                                                                                      |
| feePayerSignatures | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The fee payer's signatures.                                                                                                                                                                                                                                                                                                                        |

### RLP Encoding for Signature of the Sender <a href="#rlp-encoding-for-signature-of-the-sender" id="rlp-encoding-for-signature-of-the-sender"></a>

To make a signature of the sender, RLP serialization should be done like the following:

```javascript
SigRLP = encode([encode([type, nonce, gasPrice, gas, to, value, from, input, feeRatio]), chainid, 0, 0])
SigHash = keccak256(SigRLP)
Signature = sign(SigHash, <the sender's private key>)
```

### RLP Encoding for Signature of the Fee Payer <a href="#rlp-encoding-for-signature-of-the-fee-payer" id="rlp-encoding-for-signature-of-the-fee-payer"></a>

To make a signature of the fee payer, RLP serialization should be done like the following:

```javascript
SigFeePayerRLP = encode([encode([type, nonce, gasPrice, gas, to, value, from, input, feeRatio]), feePayer, chainid, 0, 0])
SigFeePayerHash = keccak256(SigFeePayerRLP)
SignatureFeePayer = sign(SigFeePayerHash, <the fee payer's private key>)
```

### RLP Encoding for SenderTxHash <a href="#rlp-encoding-for-sendertxhash" id="rlp-encoding-for-sendertxhash"></a>

To make a SenderTxHash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
SenderTxHashRLP = type + encode([nonce, gasPrice, gas, to, value, from, input, feeRatio, txSignatures])
SenderTxHash = keccak256(SenderTxHashRLP)
```

### RLP Encoding for Transaction Hash <a href="#rlp-encoding-for-transaction-hash" id="rlp-encoding-for-transaction-hash"></a>

To make a transaction hash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
feePayerSignatures (a single signature) = [[v, r, s]]
feePayerSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
TxHashRLP = type + encode([nonce, gasPrice, gas, to, value, from, input, feeRatio, txSignatures, feePayer, feePayerSignatures])
TxHash = keccak256(TxHashRLP)
```

### RLP Encoding (Example) <a href="#rlp-encoding-example" id="rlp-encoding-example"></a>

The following shows the result of RLP serialization and the transaction object:

```javascript
ChainID 0x1
PrivateKey 0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8
PublicKey.X 0x3a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d
PublicKey.Y 0x8072e77939dc03ba44790779b7a1025baf3003f6732430e20cd9b76d953391b3
SigRLP 0xf842b83df83b128204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0b8568656c6c6f1e018080
SigHash 0x50eef45abe0743dce17e40db185d1d85607245a545f7517a52b90f3673aff689
Signature f845f84326a0769f0afdc310289f9b24decb5bb765c8d7a87a6a4ae28edffb8b7085bbd9bc78a06a7b970eea026e60ac29bb52aee10661a4222e6bdcdfb3839a80586e584586b4
FeePayerPrivateKey 0xb9d5558443585bca6f225b935950e3f6e69f9da8a5809a83f51c3365dff53936
FeePayerPublicKey.X 0x327434d4cfc66ef8857d431419e9deebdc53a3e415edcc55382e2d417b8dd102
FeePayerPublicKey.Y 0x65fc97045707faf7b8f81ac65089d4cc71f69ad0bf1bc8559bc24f13fc284ced
SigRLPFeePayer 0xf857b83df83b128204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0b8568656c6c6f1e945a0043070275d9f6054307ee7348bd660849d90f018080
SigHashFeePayer 0x09583a871c38a4860e336bfa5f16003feec75e710cfd9186c37892cee7d9775b
SignatureFeePayer f845f84325a0c1c54bdc72ce7c08821329bf50542535fac74f4bba5de5b7881118a461d52834a03a3a64878d784f9af91c2e3ab9c90f17144c47cfd9951e3588c75063c0649ecd
TxHashRLP 0x12f8dd8204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0b8568656c6c6f1ef845f84326a0769f0afdc310289f9b24decb5bb765c8d7a87a6a4ae28edffb8b7085bbd9bc78a06a7b970eea026e60ac29bb52aee10661a4222e6bdcdfb3839a80586e584586b4945a0043070275d9f6054307ee7348bd660849d90ff845f84325a0c1c54bdc72ce7c08821329bf50542535fac74f4bba5de5b7881118a461d52834a03a3a64878d784f9af91c2e3ab9c90f17144c47cfd9951e3588c75063c0649ecd
TxHash abcb0fd8ebb8f62ac899e5211b9ba47fe948a8efd815229cc4ed9cd781464f15
SenderTxHashRLP 0x12f87b8204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0b1ef845f84326a0769f0afdc310289f9b24decb5bb765c8d7a87a6a4ae28edffb8b7085bbd9bc78a06a7b970eea026e60ac29bb52aee10661a4222e6bdcdfb3839a80586e584586b4
SenderTxHash 2c4e8cd3c68a4aacae51c695e857cfc1a019037ca71d8cd1e8ca56ec4eaf55b1

    TX(abcb0fd8ebb8f62ac899e5211b9ba47fe948a8efd815229cc4ed9cd781464f15)
    Type:          TxTypeFeeDelegatedValueTransferMemoWithRatio
    From:          0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B
    To:            0x7b65B75d204aBed71587c9E519a89277766EE1d0
    Nonce:         1234
    GasPrice:      0x19
    GasLimit:      0xf4240
    Value:         0xa
    Signature:     [{"V":"0x26","R":"0x769f0afdc310289f9b24decb5bb765c8d7a87a6a4ae28edffb8b7085bbd9bc78","S":"0x6a7b970eea026e60ac29bb52aee10661a4222e6bdcdfb3839a80586e584586b4"}]
    FeePayer:      0x5A0043070275d9f6054307Ee7348bD660849D90f
    FeeRatio:      30
    FeePayerSig:   [{"V":"0x25","R":"0xc1c54bdc72ce7c08821329bf50542535fac74f4bba5de5b7881118a461d52834","S":"0x3a3a64878d784f9af91c2e3ab9c90f17144c47cfd9951e3588c75063c0649ecd"}]
    Data:          36383635366336633666
    Hex:           12f8dd8204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0b8568656c6c6f1ef845f84326a0769f0afdc310289f9b24decb5bb765c8d7a87a6a4ae28edffb8b7085bbd9bc78a06a7b970eea026e60ac29bb52aee10661a4222e6bdcdfb3839a80586e584586b4945a0043070275d9f6054307ee7348bd660849d90ff845f84325a0c1c54bdc72ce7c08821329bf50542535fac74f4bba5de5b7881118a461d52834a03a3a64878d784f9af91c2e3ab9c90f17144c47cfd9951e3588c75063c0649ecd
```

### RPC Output (Example) <a href="#rpc-output-example" id="rpc-output-example"></a>

The following shows a transaction object returned via JSON RPC.

```javascript
{
  "blockHash": "0x7ad6ed1f9955be00db8fb5452125f0e9a3c0856abb5b4cc4aed91ffc134321da",
  "blockNumber": "0x1",
  "contractAddress": null,
  "feePayer": "0x029fdce0457db02f05c4be9f67b7115cb8ea15ca",
  "feePayerSignatures": [
    {
      "V": "0x26",
      "R": "0x1f71cc0dee26dce62a987d189650ee62a6751fcde1c7f7915abaf6c0137930da",
      "S": "0x585115c7eecb3a88e3805a90be8cb6458f245029274a781afd2b867579ff73fa"
    }
  ],
  "feeRatio": "0x1e",
  "from": "0x0fcda0f2efbe1b4e61b487701ce4f2f8abc3723d",
  "gas": "0x174876e800",
  "gasPrice": "0x5d21dba00",
  "gasUsed": "0x8e94",
  "input": "0x68656c6c6f",
  "logs": [],
  "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "nonce": "0x6",
  "senderTxHash": "0xe68e9194c5448d17137f00aae392ade4d8a143c1ae4f3c5a2340a332bce009e4",
  "signatures": [
    {
      "V": "0x25",
      "R": "0x60e5da74cc0f7d73b57dc4b2a5bb7dd05d40757b47febc079e3a43769878abc3",
      "S": "0x68e16f2a7bce21e16cebbe22a3624aa5edd814dd74a70ab8aaf850cd7a4b757f"
    }
  ],
  "status": "0x1",
  "to": "0x75c3098be5e4b63fbac05838daaee378dd48098d",
  "transactionHash": "0xda18ebcf420af8a0a7acf6636711540f71b8bb65bc86e960e6a6bbb665a062f3",
  "transactionIndex": "0x6",
  "type": "TxTypeFeeDelegatedValueTransferMemoWithRatio",
  "typeInt": 18,
  "value": "0x989680"
}
```

## TxTypeFeeDelegatedSmartContractDeployWithRatio <a href="#txtypefeedelegatedsmartcontractdeploywithratio" id="txtypefeedelegatedsmartcontractdeploywithratio"></a>

TxTypeFeeDelegatedSmartContractDeployWithRatio는 스마트 컨트랙트를 배포합니다. 주어진 부담 비율의 트랜잭션 수수료는 트랜잭션 수수료 납부자가 지불합니다. The following changes will be made by this transaction type.

1. The fee payer's balance decreases by the fee ratio of the amount of the transaction fee.
2. The sender's balance decreases by the remaining transaction fee. e.g., If the `feeRatio` is 30, 30% of the fee will be paid by the fee payer, and the remaining 70% of the fee will be paid by the sender.
3. The sender's nonce increases by one.
4. A smart contract is deployed with the code in `input`. The deployed address will be returned via `contractAddress` in the receipt.
5. `value` KLAY is transferred from the sender to the recipient.

### Attributes <a href="#attributes" id="attributes"></a>

| Attribute          | Type                                      | Description                                                                                                                                                                                                                                                                                                                                        |
| ------------------ | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| type               | uint8 (Go)                                | TxTypeFeeDelegatedSmartContractDeployWithRatio의 유형입니다. 이는 0x2a이어야 합니다.                                                                                                                                                                                                                                                                             |
| nonce              | uint64 (Go)                               | A value used to uniquely identify a sender’s transaction. If two transactions with the same nonce are generated by a sender, only one is executed.                                                                                                                                                                                                 |
| gasPrice           | \*big.Int (Go)                            | A unit price of gas in `peb` the sender will pay for a transaction fee. The amount of transaction fee is calculated as `gas` \* `gasPrice`. For example, if the transaction consumes 10 units of gas and gasPrice is 10^18, the transaction fee will be 10 KLAY. See [Unit of KLAY](/content/klaytn/design/klaytn-native-coin-klay#units-of-klay). |
| gas                | uint64 (Go)                               | The maximum amount of gas the transaction is allowed to use.                                                                                                                                                                                                                                                                                       |
| to                 | \*common.Address (Go)                     | The account address that will receive the transferred value. Currently, this value must be nil. Specifying the address will be supported in the future.                                                                                                                                                                                            |
| value              | \*big.Int (Go)                            | The amount of KLAY in `peb` to be transferred.                                                                                                                                                                                                                                                                                                     |
| from               | common.Address (Go)                       | The address of the sender. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                 |
| input              | \[]byte (Go)                              | Data attached to the transaction, used for transaction execution.                                                                                                                                                                                                                                                                                  |
| humanReadable      | bool (Go)                                 | This must be false since human-readable address is not supported yet. If true, the transaction will be rejected.                                                                                                                                                                                                                                   |
| feeRatio           | uint8 (Go)                                | Fee ratio of the fee payer. The valid range is between 1 and 99. Zero(0) is not allowed. 100 and above are not allowed as well.                                                                                                                                                                                                                    |
| codeFormat         | uint8 (Go)                                | The code format of smart contract code. The supported value for now is EVM(0x00) only.                                                                                                                                                                                                                                                             |
| txSignatures       | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The sender's signatures. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                   |
| feePayer           | common.Address (Go)                       | The address of the fee payer.                                                                                                                                                                                                                                                                                                                      |
| feePayerSignatures | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The fee payer's signatures.                                                                                                                                                                                                                                                                                                                        |

### RLP Encoding for Signature of the Sender <a href="#rlp-encoding-for-signature-of-the-sender" id="rlp-encoding-for-signature-of-the-sender"></a>

To make a signature of the sender, RLP serialization should be done like the following:

```javascript
SigRLP = encode([encode([type, nonce, gasPrice, gas, to, value, from, input, humanReadable, feeRatio, codeFormat]), chainid, 0, 0])
SigHash = keccak256(SigRLP)
Signature = sign(SigHash, <the sender's private key>)
```

### RLP Encoding for Signature of the Fee Payer <a href="#rlp-encoding-for-signature-of-the-fee-payer" id="rlp-encoding-for-signature-of-the-fee-payer"></a>

To make a signature of the fee payer, RLP serialization should be done like the following:

```javascript
SigFeePayerRLP = encode([encode([type, nonce, gasPrice, gas, to, value, from, input, humanReadable, feeRatio, codeFormat]), feePayer, chainid, 0, 0])
SigFeePayerHash = keccak256(SigFeePayerRLP)
SignatureFeePayer = sign(SigFeePayerHash, <the fee payer's private key>)
```

### RLP Encoding for SenderTxHash <a href="#rlp-encoding-for-sendertxhash" id="rlp-encoding-for-sendertxhash"></a>

To make a SenderTxHash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
SenderTxHashRLP = type + encode([nonce, gasPrice, gas, to, value, from, input, humanReadable, feeRatio, codeFormat, txSignatures])
SenderTxHash = keccak256(SenderTxHashRLP)
```

### RLP Encoding for Transaction Hash <a href="#rlp-encoding-for-transaction-hash" id="rlp-encoding-for-transaction-hash"></a>

To make a transaction hash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
feePayerSignatures (a single signature) = [[v, r, s]]
feePayerSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
TxHashRLP = type + encode([nonce, gasPrice, gas, to, value, from, input, humanReadable, feeRatio, codeFormat, txSignatures, feePayer, feePayerSignatures])
TxHash = keccak256(TxHashRLP)
```

### RLP Encoding (Example) <a href="#rlp-encoding-example" id="rlp-encoding-example"></a>

The following shows the result of RLP serialization and the transaction object:

```javascript
ChainID 0x1
PrivateKey 0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8
PublicKey.X 0x3a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d
PublicKey.Y 0x8072e77939dc03ba44790779b7a1025baf3003f6732430e20cd9b76d953391b3
SigRLP 0xf90241b9023bf902382a8204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0bb901fe608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f0029011e80018080
SigHash 0x000db9e2246975d7242e2fb45279ff42bc0269e544e3b1589ea78e760775cc2c
Signature f845f84326a0cfe8dc29d31916b3f661a4774cb8d44d39ae700a9fb6ca04327f84bbe4de1486a01616e09ced403420cac1363d14e705b7a323518b1ce5124b16f06871c00ac424
FeePayerPrivateKey 0xb9d5558443585bca6f225b935950e3f6e69f9da8a5809a83f51c3365dff53936
FeePayerPublicKey.X 0x327434d4cfc66ef8857d431419e9deebdc53a3e415edcc55382e2d417b8dd102
FeePayerPublicKey.Y 0x65fc97045707faf7b8f81ac65089d4cc71f69ad0bf1bc8559bc24f13fc284ced
SigRLPFeePayer 0xf90256b9023bf902382a8204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0bb901fe608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f0029011e80945a0043070275d9f6054307ee7348bd660849d90f018080
SigHashFeePayer 0xedd4031ccfb27867cbd856192cec0a538ab25f6bc632f3075bf7be8368983cea
SignatureFeePayer f845f84325a0e29dae81defc027f059cd6a55ff74156b9c5bdb811460f09fc8d167c01aaaea1a04eba34d4d5ebbce60e4998f03b7a4658263bb21063ddf68ad3b088d670de47c8
TxHashRLP 0x2af902da8204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0bb901fe608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f0029011e80f845f84326a0cfe8dc29d31916b3f661a4774cb8d44d39ae700a9fb6ca04327f84bbe4de1486a01616e09ced403420cac1363d14e705b7a323518b1ce5124b16f06871c00ac424945a0043070275d9f6054307ee7348bd660849d90ff845f84325a0e29dae81defc027f059cd6a55ff74156b9c5bdb811460f09fc8d167c01aaaea1a04eba34d4d5ebbce60e4998f03b7a4658263bb21063ddf68ad3b088d670de47c8
TxHash 54b6f267c2dd508ffdd9d41fd6d04847ad975cede8fcd4d5af58ca959c534946
SenderTxHashRLP 0x2af9027e8204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0bb901fe608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f0029011e80f845f84326a0cfe8dc29d31916b3f661a4774cb8d44d39ae700a9fb6ca04327f84bbe4de1486a01616e09ced403420cac1363d14e705b7a323518b1ce5124b16f06871c00ac424
SenderTxHash 57dfef9c923cba182cca00fa65d45aaf619613d843d585d3c4026a3bd0797366

    TX(54b6f267c2dd508ffdd9d41fd6d04847ad975cede8fcd4d5af58ca959c534946)
    Type:          TxTypeFeeDelegatedSmartContractDeployWithRatio
    From:          0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B
    To:            0x7b65B75d204aBed71587c9E519a89277766EE1d0
    Nonce:         1234
    GasPrice:      0x19
    GasLimit:      0xf4240
    Value:         0xa
    Data:          363038303630343035323334383031353631303031303537363030303830666435623530363130316465383036313030323036303030333936303030663330303630383036303430353236303034333631303631303036313537363366666666666666663763303130303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303630303033353034313636333161333964386566383131343631303038303537383036333633353335383662313436313030613735373830363337306130383233313134363130306361353738303633666436623765663831343631303066383537356233333630303039303831353236303031363032303532363034303831323038303534333439303831303139303931353538313534303139303535303035623334383031353631303038633537363030303830666435623530363130303935363130313064353635623630343038303531393138323532353139303831393030333630323030313930663335623631303063383733666666666666666666666666666666666666666666666666666666666666666666666666666666663630303433353136363130313133353635623030356233343830313536313030643635373630303038306664356235303631303039353733666666666666666666666666666666666666666666666666666666666666666666666666666666663630303433353136363130313437353635623334383031353631303130343537363030303830666435623530363130306338363130313539353635623630303035343831353635623733666666666666666666666666666666666666666666666666666666666666666666666666666666663136363030303930383135323630303136303230353236303430383132303830353433343930383130313930393135353831353430313930353535363562363030313630323035323630303039303831353236303430393032303534383135363562333336303030393038313532363030313630323035323630343038313230383035343930383239303535393038313131313536313031616635373630343035313333393038323135363130386663303239303833393036303030383138313831383538383838663139333530353035303530313536313031396335373631303161663536356233333630303039303831353236303031363032303532363034303930323038313930353535623530353630306131363536323761376137323330353832303632376361343662623039343738613031353736323830366363303063343331323330353031313138633763323663333061633538633465303965353163346630303239
    HumanReadable: true
    Signature:     [{"V":"0x26","R":"0xcfe8dc29d31916b3f661a4774cb8d44d39ae700a9fb6ca04327f84bbe4de1486","S":"0x1616e09ced403420cac1363d14e705b7a323518b1ce5124b16f06871c00ac424"}]
    FeePayer:      0x5A0043070275d9f6054307Ee7348bD660849D90f
    FeeRatio:      30
    CodeFormat:    CodeFormatEVM
    FeePayerSig:   [{"V":"0x25","R":"0xe29dae81defc027f059cd6a55ff74156b9c5bdb811460f09fc8d167c01aaaea1","S":"0x4eba34d4d5ebbce60e4998f03b7a4658263bb21063ddf68ad3b088d670de47c8"}]
    Hex:           2af902da8204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0bb901fe608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f0029011e80f845f84326a0cfe8dc29d31916b3f661a4774cb8d44d39ae700a9fb6ca04327f84bbe4de1486a01616e09ced403420cac1363d14e705b7a323518b1ce5124b16f06871c00ac424945a0043070275d9f6054307ee7348bd660849d90ff845f84325a0e29dae81defc027f059cd6a55ff74156b9c5bdb811460f09fc8d167c01aaaea1a04eba34d4d5ebbce60e4998f03b7a4658263bb21063ddf68ad3b088d670de47c8
```

### RPC Output (Example) <a href="#rpc-output-example" id="rpc-output-example"></a>

The following shows a transaction object returned via JSON RPC.

```javascript
{
  "blockHash": "0x82983fe294d286e76486760e6904369285554e1744af16786c2393a956fb4ec4",
  "blockNumber": "0x2",
  "codeFormat": "0x0",
  "contractAddress": "0x636f6e7472616374332e6b6c6179746e00000000",
  "feePayer": "0x029fdce0457db02f05c4be9f67b7115cb8ea15ca",
  "feePayerSignatures": [
    {
      "V": "0x25",
      "R": "0x9dbd19852ce8d1bc36389c73aa45733ccd2af0186d78952ca2b7bf3828227c02",
      "S": "0x184f60af32203d5abd0e1ac8820887cc96189d4efc1ccddb5fb966e29a07c9cf"
    }
  ],
  "feeRatio": "0x21",
  "from": "0x0fcda0f2efbe1b4e61b487701ce4f2f8abc3723d",
  "gas": "0x174876e800",
  "gasPrice": "0x0",
  "gasUsed": "0xee6e6ed5",
  "humanReadable": true,
  "input": "0x608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f0029",
  "logs": [],
  "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "nonce": "0xc",
  "senderTxHash": "0xe24e58467268601dc5131fb9719ebbb4bed16244af05c37d916a92c98a6a62a5",
  "signatures": [
    {
      "V": "0x26",
      "R": "0xb9497df1dd5c37786570f26745112fb828fb7b6de851bc11562eab77a76462b1",
      "S": "0x6231f2945f01004e68388ad1103cb00fd4f3f8b782667030d99779ecd47d7462"
    }
  ],
  "status": "0x1",
  "to": "0x636f6e7472616374332e6b6c6179746e00000000",
  "transactionHash": "0x32944e85f2255b7ebc1101b136938a758295d57dca1203b997e7ee7873dd9eec",
  "transactionIndex": "0x5",
  "type": "TxTypeFeeDelegatedSmartContractDeployWithRatio",
  "typeInt": 42,
  "value": "0x0"
}
```

## TxTypeFeeDelegatedSmartContractExecutionWithRatio <a href="#txtypefeedelegatedsmartcontractexecutionwithratio" id="txtypefeedelegatedsmartcontractexecutionwithratio"></a>

TxTypeFeeDelegatedSmartContractExecution executes a smart contract with the given data in `input`. TxTypeFeeDelegatedSmartContractExecutionWithRatio는 `to`가 스마트 컨트랙트 계정일 때만 실행됩니다. KLAY를 외부 소유 계정으로 전송하려면 [TxTypeFeeDelegatedValueTransferWithRatio](#txtypefeedelegatedvaluetransferwithratio)를 대신 사용하십시오. The following changes will be made by this transaction type.

1. If `to` is a smart contract account, the code is executed based on `input`. Otherwise, this transaction will be rejected.
2. The fee payer's balance decreases by the fee ratio of the amount of the transaction fee.
3. The sender's balance decreases by the remaining transaction fee. e.g., If the `feeRatio` is 30, 30% of the fee will be paid by the fee payer, and the remaining 70% of the fee will be paid by the sender.
4. The sender's nonce increases by one.
5. If `value` was provided, `value` KLAY is transferred from the sender to the `to` smart contract. The contract should have a payable fallback function to receive KLAY.

### Attributes <a href="#attributes" id="attributes"></a>

| Attribute          | Type                                      | Description                                                                                                                                                                                                                                                                                                                                        |
| ------------------ | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| type               | uint8 (Go)                                | TxTypeFeeDelegatedSmartContractExecutionWithRatio의 유형입니다. 이는 0x32이어야 합니다.                                                                                                                                                                                                                                                                          |
| nonce              | uint64 (Go)                               | A value used to uniquely identify a sender’s transaction. If two transactions with the same nonce are generated by a sender, only one is executed.                                                                                                                                                                                                 |
| gasPrice           | \*big.Int (Go)                            | A unit price of gas in `peb` the sender will pay for a transaction fee. The amount of transaction fee is calculated as `gas` \* `gasPrice`. For example, if the transaction consumes 10 units of gas and gasPrice is 10^18, the transaction fee will be 10 KLAY. See [Unit of KLAY](/content/klaytn/design/klaytn-native-coin-klay#units-of-klay). |
| gas                | uint64 (Go)                               | The maximum amount of gas the transaction is allowed to use.                                                                                                                                                                                                                                                                                       |
| to                 | common.Address (Go)                       | The address of the smart contract account to be executed.                                                                                                                                                                                                                                                                                          |
| value              | \*big.Int (Go)                            | The amount of KLAY in `peb` to be transferred.                                                                                                                                                                                                                                                                                                     |
| from               | common.Address (Go)                       | The address of the sender. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                 |
| input              | \[]byte (Go)                              | Data attached to the transaction, used for transaction execution.                                                                                                                                                                                                                                                                                  |
| feeRatio           | uint8 (Go)                                | Fee ratio of the fee payer. The valid range is between 1 and 99. Zero(0) is not allowed. 100 and above are not allowed as well.                                                                                                                                                                                                                    |
| txSignatures       | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The sender's signatures. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                   |
| feePayer           | common.Address (Go)                       | The address of the fee payer.                                                                                                                                                                                                                                                                                                                      |
| feePayerSignatures | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The fee payer's signatures.                                                                                                                                                                                                                                                                                                                        |

### RLP Encoding for Signature of the Sender <a href="#rlp-encoding-for-signature-of-the-sender" id="rlp-encoding-for-signature-of-the-sender"></a>

To make a signature of the sender, RLP serialization should be done like the following:

```javascript
SigRLP = encode([encode([type, nonce, gasPrice, gas, to, value, from, input, feeRatio]), chainid, 0, 0])
SigHash = keccak256(SigRLP)
Signature = sign(SigHash, <the sender's private key>)
```

### RLP Encoding for Signature of the Fee Payer <a href="#rlp-encoding-for-signature-of-the-fee-payer" id="rlp-encoding-for-signature-of-the-fee-payer"></a>

To make a signature of the fee payer, RLP serialization should be done like the following:

```javascript
SigFeePayerRLP = encode([encode([type, nonce, gasPrice, gas, to, value, from, input, feeRatio]), feePayer, chainid, 0, 0])
SigFeePayerHash = keccak256(SigFeePayerRLP)
SignatureFeePayer = sign(SigFeePayerHash, <the fee payer's private key>)
```

### RLP Encoding for SenderTxHash <a href="#rlp-encoding-for-sendertxhash" id="rlp-encoding-for-sendertxhash"></a>

To make a SenderTxHash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
SenderTxHashRLP = type + encode([nonce, gasPrice, gas, to, value, from, input, feeRatio, txSignatures])
SenderTxHash = keccak256(SenderTxHashRLP)
```

### RLP Encoding for Transaction Hash <a href="#rlp-encoding-for-transaction-hash" id="rlp-encoding-for-transaction-hash"></a>

To make a transaction hash, RLP serialization should be done like the following:

```javascript
TxHashRLP = type + encode([nonce, gasPrice, gas, to, value, from, input, feeRatio, txSignatures, feePayer, feePayerSignatures])
TxHash = keccak256(TxHashRLP)
```

### RLP Encoding (Example) <a href="#rlp-encoding-example" id="rlp-encoding-example"></a>

The following shows the result of RLP serialization and the transaction object:

```javascript
ChainID 0x1
PrivateKey 0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8
PublicKey.X 0x3a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d
PublicKey.Y 0x8072e77939dc03ba44790779b7a1025baf3003f6732430e20cd9b76d953391b3
SigRLP 0xf861b85cf85a328204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0ba46353586b000000000000000000000000bc5951f055a85f41a3b62fd6f68ab7de76d299b21e018080
SigHash 0x1eeea77acecdd102a070ead80a00f388e039c11d813e6d4a63ec90bd0186b210
Signature f845f84326a074ccfee18dc28932396b85617c53784ee366303bce39a2401d8eb602cf73766fa04c937a5ab9401d2cacb3f39ba8c29dbcd44588cc5c7d0b6b4113cfa7b7d9427b
FeePayerPrivateKey 0xb9d5558443585bca6f225b935950e3f6e69f9da8a5809a83f51c3365dff53936
FeePayerPublicKey.X 0x327434d4cfc66ef8857d431419e9deebdc53a3e415edcc55382e2d417b8dd102
FeePayerPublicKey.Y 0x65fc97045707faf7b8f81ac65089d4cc71f69ad0bf1bc8559bc24f13fc284ced
SigRLPFeePayer 0xf876b85cf85a328204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0ba46353586b000000000000000000000000bc5951f055a85f41a3b62fd6f68ab7de76d299b21e945a0043070275d9f6054307ee7348bd660849d90f018080
SigHashFeePayer 0x8a13f42530219cddb490108e38c48e7b58bc02a82f4d797d8f4d85eb16f6d6a5
SignatureFeePayer f845f84325a04a4997524694d535976d7343c1e3a260f99ba53fcb5477e2b96216ec96ebb565a00f8cb31a35399d2b0fbbfa39f259c819a15370706c0449952c7cfc682d200d7c
TxHashRLP 0x32f8fc8204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0ba46353586b000000000000000000000000bc5951f055a85f41a3b62fd6f68ab7de76d299b21ef845f84326a074ccfee18dc28932396b85617c53784ee366303bce39a2401d8eb602cf73766fa04c937a5ab9401d2cacb3f39ba8c29dbcd44588cc5c7d0b6b4113cfa7b7d9427b945a0043070275d9f6054307ee7348bd660849d90ff845f84325a04a4997524694d535976d7343c1e3a260f99ba53fcb5477e2b96216ec96ebb565a00f8cb31a35399d2b0fbbfa39f259c819a15370706c0449952c7cfc682d200d7c
TxHash b204e530f2a7f010d65b6f0f7639d1e9fc8add73e3a0ff1551b11585c36d3bdb
SenderTxHashRLP 0x32f8a08204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0ba46353586b000000000000000000000000bc5951f055a85f41a3b62fd6f68ab7de76d299b21ef845f84326a074ccfee18dc28932396b85617c53784ee366303bce39a2401d8eb602cf73766fa04c937a5ab9401d2cacb3f39ba8c29dbcd44588cc5c7d0b6b4113cfa7b7d9427b
SenderTxHash d5e22319cbf020d422d8ba3a07da9d99b9300826637af85b4e061805dcb2c1b0

    TX(b204e530f2a7f010d65b6f0f7639d1e9fc8add73e3a0ff1551b11585c36d3bdb)
    Type:          TxTypeFeeDelegatedSmartContractExecutionWithRatio
    From:          0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B
    To:            0x7b65B75d204aBed71587c9E519a89277766EE1d0
    Nonce:         1234
    GasPrice:      0x19
    GasLimit:      0xf4240
    Value:         0xa
    Data:          363335333538366230303030303030303030303030303030303030303030303062633539353166303535613835663431613362363266643666363861623764653736643239396232
    Signature:     [{"V":"0x26","R":"0x74ccfee18dc28932396b85617c53784ee366303bce39a2401d8eb602cf73766f","S":"0x4c937a5ab9401d2cacb3f39ba8c29dbcd44588cc5c7d0b6b4113cfa7b7d9427b"}]
    FeePayer:      0x5A0043070275d9f6054307Ee7348bD660849D90f
    FeeRatio:      30
    FeePayerSig:   [{"V":"0x25","R":"0x4a4997524694d535976d7343c1e3a260f99ba53fcb5477e2b96216ec96ebb565","S":"0xf8cb31a35399d2b0fbbfa39f259c819a15370706c0449952c7cfc682d200d7c"}]
    Hex:           32f8fc8204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a94a94f5374fce5edbc8e2a8697c15331677e6ebf0ba46353586b000000000000000000000000bc5951f055a85f41a3b62fd6f68ab7de76d299b21ef845f84326a074ccfee18dc28932396b85617c53784ee366303bce39a2401d8eb602cf73766fa04c937a5ab9401d2cacb3f39ba8c29dbcd44588cc5c7d0b6b4113cfa7b7d9427b945a0043070275d9f6054307ee7348bd660849d90ff845f84325a04a4997524694d535976d7343c1e3a260f99ba53fcb5477e2b96216ec96ebb565a00f8cb31a35399d2b0fbbfa39f259c819a15370706c0449952c7cfc682d200d7c
```

### RPC Output (Example) <a href="#rpc-output-example" id="rpc-output-example"></a>

The following shows a transaction object returned via JSON RPC.

```javascript
{
  "blockHash": "0x82983fe294d286e76486760e6904369285554e1744af16786c2393a956fb4ec4",
  "blockNumber": "0x2",
  "contractAddress": null,
  "feePayer": "0x029fdce0457db02f05c4be9f67b7115cb8ea15ca",
  "feePayerSignatures": [
    {
      "V": "0x26",
      "R": "0xfd7cbb13af34814ae5072b7078e9d98ca1806859f452c7369c88fed70150ddee",
      "S": "0x6edee3341b62a2ef1488636a9395bc236ebcdfebc76ee3c933d48a65ea89440e"
    }
  ],
  "feeRatio": "0x42",
  "from": "0x0fcda0f2efbe1b4e61b487701ce4f2f8abc3723d",
  "gas": "0x174876e800",
  "gasPrice": "0x0",
  "gasUsed": "0xc444",
  "input": "0x6353586b0000000000000000000000000fcda0f2efbe1b4e61b487701ce4f2f8abc3723d",
  "logs": [],
  "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "nonce": "0xf",
  "senderTxHash": "0x5545f40855ac02770f8738629d2e81bd3d04df3d90bb2b6e676a10e747c0d946",
  "signatures": [
    {
      "V": "0x26",
      "R": "0xaf1fdf0874424ed6d86b1408d24e2dff36046669cf9d99282bec4a50713adfa6",
      "S": "0x20f25bf30b0d906cee734396914a5497076a7f50ce83954b09c9f46415af8f1"
    }
  ],
  "status": "0x1",
  "to": "0x636f6e74726163742e6b6c6179746e0000000000",
  "transactionHash": "0xc4af8d6b3353ad3ad240a747d185a094c6e751373c3c08c669eb37c50f01b7b1",
  "transactionIndex": "0x8",
  "type": "TxTypeFeeDelegatedSmartContractExecutionWithRatio",
  "typeInt": 50,
  "value": "0xa"
}
```

## TxTypeFeeDelegatedAccountUpdateWithRatio <a href="#txtypefeedelegatedaccountupdatewithratio" id="txtypefeedelegatedaccountupdatewithratio"></a>

TxTypeFeeDelegatedAccountUpdateWithRatio는 해당 계정의 키를 업데이트합니다. The given ratio of the transaction fee is paid by the fee payer. The following changes will take place by this transaction type.

1. The fee payer's balance decreases by the fee ratio of the amount of the transaction fee.
2. The sender's balance decreases by the remaining transaction fee. e.g., If the `feeRatio` is 30, 30% of the fee will be paid by the fee payer, and the remaining 70% of the fee will be paid by the sender.
3. The sender's nonce increases by one.
4. The account's key is updated with `key`.
5. 이 트랜잭션이 실행되고 나면 추후에 계정에서 보내진 트랜잭션은 이 `key`에 의해 검증됩니다.

### Attributes <a href="#attributes" id="attributes"></a>

| Attribute          | Type                                      | Description                                                                                                                                                                                                                                                                                                                      |
| ------------------ | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| type               | uint8 (Go)                                | TxTypeFeeDelegatedCancelWithRatio의 유형입니다. 이는 0x22이어야 합니다.                                                                                                                                                                                                                                                                        |
| nonce              | uint64 (Go)                               | A value used to uniquely identify a sender’s transaction. If two transactions with the same nonce are generated by a sender, only one is executed.                                                                                                                                                                               |
| gasPrice           | \*big.Int (Go)                            | A multiplier to get how much the sender will pay in tokens. The amount of tokens the sender will pay is calculated via `gas` \* `gasPrice`. For example, the sender will pay 10 KLAY for a transaction fee if gas is 10 and gasPrice is 10^18. See [Unit of KLAY](/content/klaytn/design/klaytn-native-coin-klay#units-of-klay). |
| gas                | uint64 (Go)                               | The maximum amount of transaction fee the transaction is allowed to use.                                                                                                                                                                                                                                                         |
| from               | common.Address (Go)                       | The address of the sender. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                               |
| key                | AccountKey (Go)                           | [AccountKey](/content/klaytn/design/accounts#account-key) to be updated to the account.                                                                                                                                                                                                                                          |
| feeRatio           | uint8 (Go)                                | Fee ratio of the fee payer. The valid range is between 1 and 99. Zero(0) is not allowed. 100 and above are not allowed as well.                                                                                                                                                                                                  |
| txSignatures       | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The sender's signatures. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                 |
| feePayer           | common.Address (Go)                       | The address of the fee payer.                                                                                                                                                                                                                                                                                                    |
| feePayerSignatures | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The fee payer's signatures.                                                                                                                                                                                                                                                                                                      |

### RLP Encoding for Signature of the Sender <a href="#rlp-encoding-for-signature-of-the-sender" id="rlp-encoding-for-signature-of-the-sender"></a>

To make a signature of the sender, RLP serialization should be done like the following:

```javascript
SigRLP = encode([encode([type, nonce, gasPrice, gas, from, rlpEncodedKey, feeRatio]), chainid, 0, 0])
SigHash = keccak256(SigRLP)
Signature = sign(SigHash, <the sender's private key>)
```

### RLP Encoding for Signature of the Fee Payer <a href="#rlp-encoding-for-signature-of-the-fee-payer" id="rlp-encoding-for-signature-of-the-fee-payer"></a>

To make a signature of the fee payer, RLP serialization should be done like the following:

```javascript
SigFeePayerRLP = encode([encode([type, nonce, gasPrice, gas, from, rlpEncodedKey, feeRatio]), feePayer, chainid, 0, 0])
SigFeePayerHash = keccak256(SigFeePayerRLP)
SignatureFeePayer = sign(SigFeePayerHash, <the fee payer's private key>)
```

### RLP Encoding for SenderTxHash <a href="#rlp-encoding-for-sendertxhash" id="rlp-encoding-for-sendertxhash"></a>

To make a SenderTxHash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
SenderTxHashRLP = type + encode([nonce, gasPrice, gas, from, rlpEncodedKey, feeRatio, txSignatures])
SenderTxHash = keccak256(SenderTxHashRLP)
```

### RLP Encoding for Transaction Hash <a href="#rlp-encoding-for-transaction-hash" id="rlp-encoding-for-transaction-hash"></a>

To make a transaction hash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
feePayerSignatures (a single signature) = [[v, r, s]]
feePayerSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
TxHashRLP = type + encode([nonce, gasPrice, gas, from, rlpEncodedKey, feeRatio, txSignatures, feePayer, feePayerSignatures])
TxHash = keccak256(TxHashRLP)
```

### RLP Encoding (Example) <a href="#rlp-encoding-example" id="rlp-encoding-example"></a>

The following shows the result of RLP serialization and the transaction object:

```javascript
ChainID 0x1
PrivateKey 0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8
PublicKey.X 0x3a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d
PublicKey.Y 0x8072e77939dc03ba44790779b7a1025baf3003f6732430e20cd9b76d953391b3
SigRLP 0xf84ab845f843228204d219830f424094a94f5374fce5edbc8e2a8697c15331677e6ebf0ba302a1033a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d1e018080
SigHash 0x706ba7cd01e44008077a2abeafc3aacd64cbf210f49c64983f295a2e4cc03216
Signature f845f84326a00e5929f96dec2b41343a9e6f0150eef08741fe7dcece88cc5936c49ed19051dca05a07b07017190e0baba32bdf6352f5a358a2798ed3c56e704a63819b87cf8e3f
FeePayerPrivateKey 0xb9d5558443585bca6f225b935950e3f6e69f9da8a5809a83f51c3365dff53936
FeePayerPublicKey.X 0x327434d4cfc66ef8857d431419e9deebdc53a3e415edcc55382e2d417b8dd102
FeePayerPublicKey.Y 0x65fc97045707faf7b8f81ac65089d4cc71f69ad0bf1bc8559bc24f13fc284ced
SigRLPFeePayer 0xf85fb845f843228204d219830f424094a94f5374fce5edbc8e2a8697c15331677e6ebf0ba302a1033a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d1e945a0043070275d9f6054307ee7348bd660849d90f018080
SigHashFeePayer 0xd2a51cefec667747890e6bd11fd068e8796b5446f77e152367eaa3cf98c96b30
SignatureFeePayer f845f84326a0cf8d102de7c6b0a41d3f02aefb7e419522341734c98af233408298d0c424c04ba00286f89cab4668f728d7c269997116a49b80cec8776fc64e60588a9268571e35
TxHashRLP 0x22f8e58204d219830f424094a94f5374fce5edbc8e2a8697c15331677e6ebf0ba302a1033a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d1ef845f84326a00e5929f96dec2b41343a9e6f0150eef08741fe7dcece88cc5936c49ed19051dca05a07b07017190e0baba32bdf6352f5a358a2798ed3c56e704a63819b87cf8e3f945a0043070275d9f6054307ee7348bd660849d90ff845f84326a0cf8d102de7c6b0a41d3f02aefb7e419522341734c98af233408298d0c424c04ba00286f89cab4668f728d7c269997116a49b80cec8776fc64e60588a9268571e35
TxHash 276f02c25ca4ced081dcfbb836755ced574993b047e648a583ed8d4144b3813f
SenderTxHashRLP 0x22f8898204d219830f424094a94f5374fce5edbc8e2a8697c15331677e6ebf0ba302a1033a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d1ef845f84326a00e5929f96dec2b41343a9e6f0150eef08741fe7dcece88cc5936c49ed19051dca05a07b07017190e0baba32bdf6352f5a358a2798ed3c56e704a63819b87cf8e3f
SenderTxHash e1d87538509549f4a1eb418f986bc53dc77b7eec3b2150f75cd787951d3e4b7f

    TX(276f02c25ca4ced081dcfbb836755ced574993b047e648a583ed8d4144b3813f)
    Type:          TxTypeFeeDelegatedAccountUpdateWithRatio
    From:          0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B
    Nonce:         1234
    GasPrice:      0x19
    GasLimit:      0xf4240
    Key:           AccountKeyPublic: S256Pubkey:{"x":"0x3a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d","y":"0x8072e77939dc03ba44790779b7a1025baf3003f6732430e20cd9b76d953391b3"}
    Signature:     [{"V":"0x26","R":"0xe5929f96dec2b41343a9e6f0150eef08741fe7dcece88cc5936c49ed19051dc","S":"0x5a07b07017190e0baba32bdf6352f5a358a2798ed3c56e704a63819b87cf8e3f"}]
    FeePayer:      0x5A0043070275d9f6054307Ee7348bD660849D90f
    FeeRatio:      30
    FeePayerSig:   [{"V":"0x26","R":"0xcf8d102de7c6b0a41d3f02aefb7e419522341734c98af233408298d0c424c04b","S":"0x286f89cab4668f728d7c269997116a49b80cec8776fc64e60588a9268571e35"}]
    Hex:           22f8e58204d219830f424094a94f5374fce5edbc8e2a8697c15331677e6ebf0ba302a1033a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d1ef845f84326a00e5929f96dec2b41343a9e6f0150eef08741fe7dcece88cc5936c49ed19051dca05a07b07017190e0baba32bdf6352f5a358a2798ed3c56e704a63819b87cf8e3f945a0043070275d9f6054307ee7348bd660849d90ff845f84326a0cf8d102de7c6b0a41d3f02aefb7e419522341734c98af233408298d0c424c04ba00286f89cab4668f728d7c269997116a49b80cec8776fc64e60588a9268571e35
```

### RPC Output (Example) <a href="#rpc-output-example" id="rpc-output-example"></a>

The following shows a transaction object returned via JSON RPC.

```javascript
{
  "blockHash": "0x82983fe294d286e76486760e6904369285554e1744af16786c2393a956fb4ec4",
  "blockNumber": "0x2",
  "contractAddress": null,
  "feePayer": "0x0fcda0f2efbe1b4e61b487701ce4f2f8abc3723d",
  "feePayerSignatures": [
    {
      "V": "0x25",
      "R": "0xfa3690925bae82ba662abe6d3af8993b7a7994d9f922cb1ae83c59c4a26a3b70",
      "S": "0x2bd481ddf40cb813dde5f67db0e3a6ad9ea46758ef97580a709b301c21530246"
    }
  ],
  "feeRatio": "0xb",
  "from": "0x636f6c696e332e6b6c6179746e00000000000000",
  "gas": "0x174876e800",
  "gasPrice": "0x5d21dba00",
  "gasUsed": "0xdac0",
  "key": "0x02a102c8785266510368d9372badd4c7f4a94b692e82ba74e0b5e26b34558b0f081447",
  "logs": [],
  "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "nonce": "0x0",
  "senderTxHash": "0x74be8f01f10a497dbe9ed10659ac8c4579b37f8b5022b9f7eec6362262d44845",
  "signatures": [
    {
      "V": "0x25",
      "R": "0xd17d2ae2290b35c560289797c955fa5dc1cc25606cfd198584665917da6795ff",
      "S": "0x7bc0450ff7319ccdbf50d38095501b895717cac775c6897d2381e7182aa25742"
    }
  ],
  "status": "0x1",
  "transactionHash": "0x90ccbf85ffd1f7e74620840fd9d270e030c6719e3c7b70bb8796c1cedf02fe88",
  "transactionIndex": "0x1",
  "type": "TxTypeFeeDelegatedAccountUpdateWithRatio",
  "typeInt": 34
}
```

## TxTypeFeeDelegatedCancelWithRatio <a href="#txtypefeedelegatedcancelwithratio" id="txtypefeedelegatedcancelwithratio"></a>

TxTypeFeeDelegatedCancelWithRatio는 트랜잭션 풀에서 같은 논스를 가진 트랜잭션을 취소합니다. For more details, see [TxTypeCancel](/content/klaytn/design/transactions/basic#txtypecancel).

The following changes will apply by this transaction type. 1. 트랜잭션 수수료 납부자의 잔액은 트랜잭션 수수료의 주어진 수수료 부담 비율만큼 감소합니다. 2. The sender's balance decreases by the remaining transaction fee. 3. The sender's nonce increases by one.

### Attributes <a href="#attributes" id="attributes"></a>

| Attribute          | Description                               | Type                                                                                                                                                                                                                                                                                                                                               |
| ------------------ | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| type               | uint8 (Go)                                | TxTypeFeeDelegatedCancelWithRatio의 유형입니다. 이는 0x3a이어야 합니다.                                                                                                                                                                                                                                                                                          |
| nonce              | uint64 (Go)                               | A value used to uniquely identify a sender’s transaction. If two transactions with the same nonce are generated by a sender, only one is executed.                                                                                                                                                                                                 |
| gasPrice           | \*big.Int (Go)                            | A unit price of gas in `peb` the sender will pay for a transaction fee. The amount of transaction fee is calculated as `gas` \* `gasPrice`. For example, if the transaction consumes 10 units of gas and gasPrice is 10^18, the transaction fee will be 10 KLAY. See [Unit of KLAY](/content/klaytn/design/klaytn-native-coin-klay#units-of-klay). |
| gas                | uint64 (Go)                               | The maximum amount of transaction fee the transaction is allowed to use.                                                                                                                                                                                                                                                                           |
| from               | common.Address (Go)                       | The address of the sender. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                 |
| feeRatio           | uint8 (Go)                                | Fee ratio of the fee payer. The valid range is between 1 and 99. Zero(0) is not allowed. 100 and above are not allowed as well.                                                                                                                                                                                                                    |
| txSignatures       | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The sender's signatures. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                   |
| feePayer           | common.Address (Go)                       | The address of the fee payer.                                                                                                                                                                                                                                                                                                                      |
| feePayerSignatures | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The fee payer's signatures.                                                                                                                                                                                                                                                                                                                        |

### RLP Encoding for Signature of the Sender <a href="#rlp-encoding-for-signature-of-the-sender" id="rlp-encoding-for-signature-of-the-sender"></a>

To make a signature of the sender, RLP serialization should be done like the following:

```javascript
SigRLP = encode([encode([type, nonce, gasPrice, gas, from, feeRatio]), chainid, 0, 0])
SigHash = keccak256(SigRLP)
Signature = sign(SigHash, <the sender's private key>)
```

### RLP Encoding for Signature of the Fee Payer <a href="#rlp-encoding-for-signature-of-the-fee-payer" id="rlp-encoding-for-signature-of-the-fee-payer"></a>

To make a signature of the fee payer, RLP serialization should be done like the following:

```javascript
SigFeePayerRLP = encode([encode([type, nonce, gasPrice, gas, from, feeRatio]), feePayer, chainid, 0, 0])
SigFeePayerHash = keccak256(SigFeePayerRLP)
SignatureFeePayer = sign(SigFeePayerHash, <the fee payer's private key>)
```

### RLP Encoding for SenderTxHash <a href="#rlp-encoding-for-sendertxhash" id="rlp-encoding-for-sendertxhash"></a>

To make a SenderTxHash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
SenderTxHashRLP = type + encode([nonce, gasPrice, gas, from, feeRatio, txSignatures])
SenderTxHash = keccak256(SenderTxHashRLP)
```

### RLP Encoding for Transaction Hash <a href="#rlp-encoding-for-transaction-hash" id="rlp-encoding-for-transaction-hash"></a>

To make a transaction hash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
feePayerSignatures (a single signature) = [[v, r, s]]
feePayerSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
TxHashRLP = type + encode([nonce, gasPricke, gas, from, feeRatio, txSignatures, feePayer, feePayerSignatures])
TxHash = keccak256(TxHashRLP)
```

### RLP Encoding (Example) <a href="#rlp-encoding-example" id="rlp-encoding-example"></a>

The following shows the result of RLP serialization and the transaction object:

```javascript
ChainID 0x1
PrivateKey 0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8
PublicKey.X 0x3a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d
PublicKey.Y 0x8072e77939dc03ba44790779b7a1025baf3003f6732430e20cd9b76d953391b3
SigRLP 0xe4a0df3a8204d219830f424094a94f5374fce5edbc8e2a8697c15331677e6ebf0b1e018080
SigHash 0xeccd1585e8e105bc034a72190c3e9312b5407736686aa0d34b1ad75320871014
Signature f845f84326a072efa47960bef40b536c72d7e03ceaf6ca5f6061eb8a3eda3545b1a78fe52ef5a062006ddaf874da205f08b3789e2d014ae37794890fc2e575bf75201563a24ba9
FeePayerPrivateKey 0xb9d5558443585bca6f225b935950e3f6e69f9da8a5809a83f51c3365dff53936
FeePayerPublicKey.X 0x327434d4cfc66ef8857d431419e9deebdc53a3e415edcc55382e2d417b8dd102
FeePayerPublicKey.Y 0x65fc97045707faf7b8f81ac65089d4cc71f69ad0bf1bc8559bc24f13fc284ced
SigRLPFeePayer 0xf839a0df3a8204d219830f424094a94f5374fce5edbc8e2a8697c15331677e6ebf0b1e945a0043070275d9f6054307ee7348bd660849d90f018080
SigHashFeePayer 0xf71b0b22d72ef59a063a865ee844e1ba0a103d707f06fb7013b3372ed169c705
SignatureFeePayer f845f84326a06ba5ef20c3049323fc94defe14ca162e28b86aa64f7cf497ac8a5520e9615614a04a0a0fc61c10b416759af0ce4ce5c09ca1060141d56d958af77050c9564df6bf
TxHashRLP 0x3af8c18204d219830f424094a94f5374fce5edbc8e2a8697c15331677e6ebf0b1ef845f84326a072efa47960bef40b536c72d7e03ceaf6ca5f6061eb8a3eda3545b1a78fe52ef5a062006ddaf874da205f08b3789e2d014ae37794890fc2e575bf75201563a24ba9945a0043070275d9f6054307ee7348bd660849d90ff845f84326a06ba5ef20c3049323fc94defe14ca162e28b86aa64f7cf497ac8a5520e9615614a04a0a0fc61c10b416759af0ce4ce5c09ca1060141d56d958af77050c9564df6bf
TxHash 63604ebf68bfee51b2e3f54ddb2f19f9ea72d32b3fc70877324531ecda25817a
SenderTxHashRLP 0x3af8658204d219830f424094a94f5374fce5edbc8e2a8697c15331677e6ebf0b1ef845f84326a072efa47960bef40b536c72d7e03ceaf6ca5f6061eb8a3eda3545b1a78fe52ef5a062006ddaf874da205f08b3789e2d014ae37794890fc2e575bf75201563a24ba9
SenderTxHash c0818be4cffbacfe29be1134e0267e10fd1afb6571f4ccc95dcc67a788bab5e7

    TX(63604ebf68bfee51b2e3f54ddb2f19f9ea72d32b3fc70877324531ecda25817a)
    Type:          TxTypeFeeDelegatedCancelWithRatio
    From:          0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B
    Nonce:         1234
    GasPrice:      0x19
    GasLimit:      0xf4240
    Signature:     [{"V":"0x26","R":"0x72efa47960bef40b536c72d7e03ceaf6ca5f6061eb8a3eda3545b1a78fe52ef5","S":"0x62006ddaf874da205f08b3789e2d014ae37794890fc2e575bf75201563a24ba9"}]
    FeePayer:      0x5A0043070275d9f6054307Ee7348bD660849D90f
    FeeRatio:      30
    FeePayerSig:   [{"V":"0x26","R":"0x6ba5ef20c3049323fc94defe14ca162e28b86aa64f7cf497ac8a5520e9615614","S":"0x4a0a0fc61c10b416759af0ce4ce5c09ca1060141d56d958af77050c9564df6bf"}]
    Hex:           3af8c18204d219830f424094a94f5374fce5edbc8e2a8697c15331677e6ebf0b1ef845f84326a072efa47960bef40b536c72d7e03ceaf6ca5f6061eb8a3eda3545b1a78fe52ef5a062006ddaf874da205f08b3789e2d014ae37794890fc2e575bf75201563a24ba9945a0043070275d9f6054307ee7348bd660849d90ff845f84326a06ba5ef20c3049323fc94defe14ca162e28b86aa64f7cf497ac8a5520e9615614a04a0a0fc61c10b416759af0ce4ce5c09ca1060141d56d958af77050c9564df6bf
```

### RPC Output (Example) <a href="#rpc-output-example" id="rpc-output-example"></a>

The following shows a transaction object returned via JSON RPC.

```javascript
{
  "blockHash": "0x82983fe294d286e76486760e6904369285554e1744af16786c2393a956fb4ec4",
  "blockNumber": "0x2",
  "contractAddress": null,
  "feePayer": "0x029fdce0457db02f05c4be9f67b7115cb8ea15ca",
  "feePayerSignatures": [
    {
      "V": "0x25",
      "R": "0x26c8b5038e9f7ff580f3323b8a06b6eb1b6ab13cac11c30de6c9b64230bdb992",
      "S": "0x6c4be67ace8551237e675da2b7b32ec2d7d7e07abf2eb299ebec6cc444460e13"
    }
  ],
  "feeRatio": "0x58",
  "from": "0x0fcda0f2efbe1b4e61b487701ce4f2f8abc3723d",
  "gas": "0x174876e800",
  "gasPrice": "0x0",
  "gasUsed": "0x8ca0",
  "logs": [],
  "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "nonce": "0x12",
  "senderTxHash": "0xc9d2f558f6883bfea5113ce900499354fcb0004ff901dec51db7a5d80c3a7868",
  "signatures": [
    {
      "V": "0x26",
      "R": "0x88a484d1cc59824e05b933348df6ebe7b82ac68766a85e2aa5636c136ee2834c",
      "S": "0x104fee953e1a015f26b35da57acf15aa01eb5c6c0e79965200c3fe813003a4fe"
    }
  ],
  "status": "0x1",
  "transactionHash": "0x50c6840fee3297a8ff745025cb4fd27a7e662395620ad615458ea22034f37f6c",
  "transactionIndex": "0xb",
  "type": "TxTypeFeeDelegatedCancelWithRatio",
  "typeInt": 58
}
```

## TxTypeFeeDelegatedChainDataAnchoringWithRatio <a href="#txtypefeedelegatedchaindataanchoringwithratio" id="txtypefeedelegatedchaindataanchoringwithratio"></a>

TxTypeFeeDelegatedChainDataAnchoringWithRatio는 수수료 부담 비율이 정해진 수수료 위임 트랜잭션이며 서비스체인 데이터를 Klaytn 메인체인에 앵커링합니다. Service chains periodically send this type of transaction to the Klaytn mainchain to ensure its security and credibility of data. For more details about the data anchoring, see [Anchoring](/content/installation-guide/deployment/service-chain/references/anchoring). 이 트랜잭션은 수수료 납부자의 수수료 부담 비율이 정해진 수수료 위임 트랜잭션이므로, 트랜잭션 수수료 납부자는 오직 정해진 비율의 트랜잭션 수수료만 납부하며 나머지 트랜잭션 수수료는 트랜잭션 발신자가 부담합니다. Be mindful that it is not allowed to send this transaction via RPC. Currently, this transaction is executed through private p2p channels for security reasons. This transaction does not change the state of the Klaytn blockchain except the sender's nonce being increased by one.

### Attributes <a href="#attributes" id="attributes"></a>

| Attribute          | Type                                      | Description                                                                                                                                                                                                                                                                                                                                        |
| ------------------ | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| type               | uint8 (Go)                                | TxTypeFeeDelegatedChainDataAnchoringWithRatio의 타입입니다. 이는 0x4a이어야 합니다.                                                                                                                                                                                                                                                                              |
| nonce              | uint64 (Go)                               | A value used to uniquely identify a sender’s transaction. If two transactions with the same nonce are generated by a sender, only one is executed.                                                                                                                                                                                                 |
| gasPrice           | \*big.Int (Go)                            | A unit price of gas in `peb` the sender will pay for a transaction fee. The amount of transaction fee is calculated as `gas` \* `gasPrice`. For example, if the transaction consumes 10 units of gas and gasPrice is 10^18, the transaction fee will be 10 KLAY. See [Unit of KLAY](/content/klaytn/design/klaytn-native-coin-klay#units-of-klay). |
| gas                | uint64 (Go)                               | The maximum amount of transaction fee the transaction is allowed to use.                                                                                                                                                                                                                                                                           |
| from               | common.Address (Go)                       | The address of the sender. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                 |
| feeRatio           | uint8 (Go)                                | Fee ratio of the fee payer. The valid range is between 1 and 99. Zero(0) is not allowed. 100 and above are not allowed as well.                                                                                                                                                                                                                    |
| input              | \[]byte (Go)                              | Data of the service chain.                                                                                                                                                                                                                                                                                                                         |
| txSignatures       | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The sender's signatures. For more details, see [Signature Validation of Transactions](/content/klaytn/design/transactions#signature-validation-of-transactions).                                                                                                                                                                                   |
| feePayer           | common.Address (Go)                       | The address of the fee payer.                                                                                                                                                                                                                                                                                                                      |
| feePayerSignatures | \[]{\*big.Int, \*big.Int, \*big.Int} (Go) | The fee payer's signatures.                                                                                                                                                                                                                                                                                                                        |

### RLP Encoding for Signature of the Sender <a href="#rlp-encoding-for-signature-of-the-sender" id="rlp-encoding-for-signature-of-the-sender"></a>

To make a signature of the sender, RLP serialization should be done like the following:

```javascript
SigRLP = encode([encode([type, nonce, gasPrice, gas, from, anchoredData, feeRatio]), chainid, 0, 0])
SigHash = keccak256(SigRLP)
Signature = sign(SigHash, <private key>)
```

### RLP Encoding for Signature of the Fee Payer <a href="#rlp-encoding-for-signature-of-the-fee-payer" id="rlp-encoding-for-signature-of-the-fee-payer"></a>

To make a signature of the fee payer, RLP serialization should be done like the following:

```javascript
SigFeePayerRLP = encode([encode([type, nonce, gasPrice, gas, from, anchoredData, feeRatio]), feePayer, chainid, 0, 0])
SigFeePayerHash = keccak256(SigFeePayerRLP)
SignatureFeePayer = sign(SigFeePayerHash, <the fee payer's private key>)
```

### RLP Encoding for SenderTxHash <a href="#rlp-encoding-for-sendertxhash" id="rlp-encoding-for-sendertxhash"></a>

To make a SenderTxHash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
SenderTxHashRLP = type + encode([nonce, gasPrice, gas, from, anchoredData, feeRatio, txSignatures])
SenderTxHash = keccak256(SenderTxHashRLP)
```

### RLP Encoding for Transaction Hash <a href="#rlp-encoding-for-transaction-hash" id="rlp-encoding-for-transaction-hash"></a>

To make a transaction hash, RLP serialization should be done like the following:

```javascript
txSignatures (a single signature) = [[v, r, s]]
txSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
feePayerSignatures (a single signature) = [[v, r, s]]
feePayerSignatures (two signatures) = [[v1, r1, s1], [v2, r2, s2]]
TxHashRLP = type + encode([nonce, gasPrice, gas, from, anchoredData, feeRatio, txSignatures, feePayer, feePayerSignatures])
TxHash = keccak256(TxHashRLP)
```

### RLP Encoding (Example) <a href="#rlp-encoding-example" id="rlp-encoding-example"></a>

The following shows the result of RLP serialization and the transaction object:

```javascript
ChainID 0x01
PrivateKey 0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8
PublicKey.X 0x3a514176466fa815ed481ffad09110a2d344f6c9b78c1d14afc351c3a51be33d
PublicKey.Y 0x8072e77939dc03ba44790779b7a1025baf3003f6732430e20cd9b76d953391b3
SigRLP 0xf8dcb8d7f8d54a128505d21dba0085174876e80094a94f5374fce5edbc8e2a8697c15331677e6ebf0bb8aff8ad80b8aaf8a8a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000405800658018080
SigHash 0xd79dbb964bee2d3807e214a247141a1fcb066a67de99e90750aac4a2a0b776de
Signature 0xf845f84326a0c612a243bcb3b98958e9cce1a0bc0e170291b33a7f0dbfae4b36dafb5806797da00c734423492ecc21cc53238147c359676fcec43fcc2a0e021d87bb1da49f0abf
FeePayerPrivateKey 0xb9d5558443585bca6f225b935950e3f6e69f9da8a5809a83f51c3365dff53936
FeePayerPublicKey.X 0x327434d4cfc66ef8857d431419e9deebdc53a3e415edcc55382e2d417b8dd102
FeePayerPublicKey.Y 0x65fc97045707faf7b8f81ac65089d4cc71f69ad0bf1bc8559bc24f13fc284ced
SigRLPFeePayer 0xf8f1b8d7f8d54a128505d21dba0085174876e80094a94f5374fce5edbc8e2a8697c15331677e6ebf0bb8aff8ad80b8aaf8a8a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000004058006589433f524631e573329a550296f595c820d6c65213f018080
SigHashFeePayer 0xa824ff743912239d0665d2fd43a66d57138c92834e9d338b66bcca4a0bee8fbd
SignatureFeePayer 0xf845f84325a0a3e40598b67e2bcbaa48fdd258b9d1dcfcc9cc134972560ba042430078a769a5a06707ea362e588e4e5869cffcd5a058749d823aeff13eb95dc1146faff561df32
TxHashRLP 0x4af90177128505d21dba0085174876e80094a94f5374fce5edbc8e2a8697c15331677e6ebf0bb8aff8ad80b8aaf8a8a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000405800658f845f84326a0c612a243bcb3b98958e9cce1a0bc0e170291b33a7f0dbfae4b36dafb5806797da00c734423492ecc21cc53238147c359676fcec43fcc2a0e021d87bb1da49f0abf9433f524631e573329a550296f595c820d6c65213ff845f84325a0a3e40598b67e2bcbaa48fdd258b9d1dcfcc9cc134972560ba042430078a769a5a06707ea362e588e4e5869cffcd5a058749d823aeff13eb95dc1146faff561df32
TxHash 0xc01a7c3ece18c115b58d7747669ec7c31ec5ab031a88cb49ad85a31f6dbbf915
SenderTxHashRLP 0x4af9011b128505d21dba0085174876e80094a94f5374fce5edbc8e2a8697c15331677e6ebf0bb8aff8ad80b8aaf8a8a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000405800658f845f84326a0c612a243bcb3b98958e9cce1a0bc0e170291b33a7f0dbfae4b36dafb5806797da00c734423492ecc21cc53238147c359676fcec43fcc2a0e021d87bb1da49f0abf
SenderTxHash 0xa0670c01fe39feb2d2442adf7df1957ade3c5abcde778fb5edf99c80c06aa53c

    TX(c01a7c3ece18c115b58d7747669ec7c31ec5ab031a88cb49ad85a31f6dbbf915)
    Type:          TxTypeFeeDelegatedChainDataAnchoringWithRatio
    From:          0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B
    Nonce:         18
    GasPrice:      0x5d21dba00
    GasLimit:      0x174876e800
    AnchoredData:  f8ad80b8aaf8a8a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000004058006
    Signature:     [{"V":"0x26","R":"0xc612a243bcb3b98958e9cce1a0bc0e170291b33a7f0dbfae4b36dafb5806797d","S":"0xc734423492ecc21cc53238147c359676fcec43fcc2a0e021d87bb1da49f0abf"}]
    FeePayer:      0x33f524631e573329a550296F595c820D6c65213f
    FeeRatio:      88
    FeePayerSig:   [{"V":"0x25","R":"0xa3e40598b67e2bcbaa48fdd258b9d1dcfcc9cc134972560ba042430078a769a5","S":"0x6707ea362e588e4e5869cffcd5a058749d823aeff13eb95dc1146faff561df32"}]
    Hex:           4af90177128505d21dba0085174876e80094a94f5374fce5edbc8e2a8697c15331677e6ebf0bb8aff8ad80b8aaf8a8a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000405800658f845f84326a0c612a243bcb3b98958e9cce1a0bc0e170291b33a7f0dbfae4b36dafb5806797da00c734423492ecc21cc53238147c359676fcec43fcc2a0e021d87bb1da49f0abf9433f524631e573329a550296f595c820d6c65213ff845f84325a0a3e40598b67e2bcbaa48fdd258b9d1dcfcc9cc134972560ba042430078a769a5a06707ea362e588e4e5869cffcd5a058749d823aeff13eb95dc1146faff561df32
```

### RPC Output (Example) <a href="#rpc-output-example" id="rpc-output-example"></a>

The following shows a transaction object returned via JSON RPC.

```javascript
{
    "blockHash": "0xee6c72b7d99019a941b47d77507abe015c3f00d3ff9122a2eec33d846107b842",
    "blockNumber": "0x2",
    "contractAddress": null,
    "feePayer": "0x33f524631e573329a550296f595c820d6c65213f",
    "feePayerSignatures": [
        {
            "V": "0x25",
            "R": "0xa3e40598b67e2bcbaa48fdd258b9d1dcfcc9cc134972560ba042430078a769a5",
            "S": "0x6707ea362e588e4e5869cffcd5a058749d823aeff13eb95dc1146faff561df32"
        }
    ],
    "feeRatio": "0x58",
    "from": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
    "gas": "0x174876e800",
    "gasPrice": "0x5d21dba00",
    "gasUsed": "0xd0fc",
    "input": "0xf8ad80b8aaf8a8a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000004058006",
    "logs": [],
    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "nonce": "0x12",
    "senderTxHash": "0xa0670c01fe39feb2d2442adf7df1957ade3c5abcde778fb5edf99c80c06aa53c",
    "signatures": [
        {
            "V": "0x26",
            "R": "0xc612a243bcb3b98958e9cce1a0bc0e170291b33a7f0dbfae4b36dafb5806797d",
            "S": "0xc734423492ecc21cc53238147c359676fcec43fcc2a0e021d87bb1da49f0abf"
        }
    ],
    "status": "0x1",
    "transactionHash": "0xc01a7c3ece18c115b58d7747669ec7c31ec5ab031a88cb49ad85a31f6dbbf915",
    "transactionIndex": "0xb",
    "type": "TxTypeFeeDelegatedChainDataAnchoringWithRatio",
    "typeInt": 74
}
```


# Ethereum

Klaytn provides wrapped transaction types to support Ethereum compatibility. Ethereum transaction types in Klaytn have the same attributes and RLP encoding schemes with Ethereum's design except for the single-byte type delimiter called `EthereumTxTypeEnvelope`. Therefore, users can successfully deploy transactions generated by Ethereum development tools on Klaytn. The type delimiter is also omitted when users use `eth` namespace APIs, so they can use Klaytn just as if they were using Ethereum. Using `klay` namespace APIs, users can deploy and retrieve Ethereum formatted transactions as a type of Klaytn transactions without getting confused with the existing Klaytn transaction types.

## EthereumTxTypeEnvelope <a href="#ethereumtxtypeenvelope" id="ethereumtxtypeenvelope"></a>

EthereumTxTypeEnvelope is a single-byte prefix for raw transactions that denotes Ethereum transaction types. Ethereum has adopted an extendable transaction type scheme from [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718) and it uses a type numbering system that conflicts with Klaytn's. To resolve the conflict between two different transaction type schemes, Klaytn has introduced `EthereumTxTypeEnvelope` which allows for separation and expansion for future Ethereum transaction types.

`EthereumTxTypeEnvelope` is an additional type delimiter and used only for raw transactions and type numbering. It is not used for transaction hash or signature hash. For that purpose, `EthereumTransactionType` as defined in EIPs is used.

* EthereumTxTypeEnvelope: `0x78`
* TxHashRLP : EthereumTransactionType || TransactionPayload
* RawTransaction : EthereumTxTypeEnvelope || EthereumTransactionType || TransactionPayload

## TxTypeEthereumAccessList <a href="#txtypeethereumaccesslist" id="txtypeethereumaccesslist"></a>

`TxTypeEthereumAccessList` represents a type of Ethereum transaction specified in [EIP-2930](https://eips.ethereum.org/EIPS/eip-2930). This transactions type contains an access list, a list of addresses and storage keys that the transaction is supposed to access. Since this transaction type exists to support compatibility, it only works with EOAs associated with \[AccountKeyLegacy]. EOAs associated with other account key types should use other transaction types such as `TxTypeValueTransfer`, `TxTypeSmartContractExecution`, and so on. This transaction type can create accounts, transfer tokens, deploy/execute smart contracts or a mix of the aforementioned.

{% hint style="success" %}
NOTE: Klaytn networks can process this transaction type after the `EthTxTypeCompatibleBlock`
{% endhint %}

{% hint style="success" %}
NOTE: This transaction type only supports the format of the Ethereum transaction type. Unlike [EIP-2930](https://eips.ethereum.org/EIPS/eip-2930), there are no benefits in terms of transaction fee from using access list.
{% endhint %}

### Attributes <a href="#attributes" id="attributes"></a>

| Attribute  | Type                  | Description                                                                                                                                                                                                                                                         |
| ---------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| type       | uint8 (Go)            | The type of `TxTypeEthereumAccessList` that is a concatenation of `EthereumTxTypeEnvelope` and `EthereumTransactionType`. This must be 0x7801.                                                                                                                      |
| chainId    | \*big.Int (Go)        | The destination chain ID.                                                                                                                                                                                                                                           |
| nonce      | uint64 (Go)           | A value used to uniquely identify a sender’s transaction. If two transactions with the same nonce are generated by a sender, only one is executed.                                                                                                                  |
| gasPrice   | \*big.Int (Go)        | A multiplier to get how much the sender will pay in tokens. The amount of tokens the sender will pay is calculated via `gas` \* `gasPrice`. For example, the sender will pay 10 KLAY for a transaction fee if gas is 10 and gasPrice is 10^18. See \[Unit of KLAY]. |
| gas        | uint64 (Go)           | The maximum amount of transaction fee the transaction is allowed to use.                                                                                                                                                                                            |
| to         | \*common.Address (Go) | The account address that will receive the transferred value.                                                                                                                                                                                                        |
| value      | \*big.Int (Go)        | The amount of KLAY in `peb` to be transferred.                                                                                                                                                                                                                      |
| data       | \[]byte (Go)          | Data attached to the transaction, used for transaction execution.                                                                                                                                                                                                   |
| accessList | type.AccessList (Go)  | A list of addresses and storage keys consisting of \[]\(common.Address, \[]common.Hash).                                                                                                                                                                            |
| v, r, s    | \*big.Int (Go)        | The cryptographic signature generated by the sender to let the receiver obtain the sender's address.                                                                                                                                                                |

### RLP Encoding for Signature <a href="#rlp-encoding-for-signature" id="rlp-encoding-for-signature"></a>

To make a signature for this transaction type, the RLP serialization proceeds as follows:

{% hint style="success" %}
NOTE: This type of transaction should be signed with London Signer
{% endhint %}

```javascript
SigRLP = EthereumTransactionType || encode([chainId, nonce, gasPrice, gasLimit, to, value, data, accessList])
SigHash = keccak256(SigRLP)
Signature = sign(SigHash, <private key>)
```

### RLP Encoding for SenderTxHash <a href="#rlp-encoding-for-sendertxhash" id="rlp-encoding-for-sendertxhash"></a>

To obtain `SenderTxHash` for this transaction type, the RLP serialization proceeds as follows:

```javascript
SenderTxHashRLP = EthereumTransactionType || encode([chainId, nonce, gasPrice, gasLimit, to, value, data, accessList, v, r, s])
SenderTxHash = keccak256(SenderTxHashRLP)
Signature = sign(SenderTxHash, <private key>)
```

### RLP Encoding for Transaction Hash <a href="#rlp-encoding-for-transaction-hash" id="rlp-encoding-for-transaction-hash"></a>

To make a transaction hash, the RLP serialization proceeds as follows:

```javascript
TxHashRLP = EthereumTransactionType || encode([chainId, nonce, gasPrice, gasLimit, to, value, data, accessList, v, r, s])
TxHash = keccak256(TxHashRLP)
```

### Raw Transaction <a href="#raw-transaction" id="raw-transaction"></a>

```javascript
RawTx = EthereumTxTypeEnvelope || EthereumTransactionType || encode([chainId, nonce, gasPrice, gasLimit, to, value, data, accessList, v, r, s])
```

### RLP Encoding (Example) <a href="#rlp-encoding-example" id="rlp-encoding-example"></a>

The following shows the result of the RLP serialization and the transaction object:

```javascript
    TX(3a3ab67168de40b1f8a2141a70a4e2f551f90d7814b2fbcb3ac99ad8d8d0b641)
    Contract: false
    Chaind:   0x2
    From:     a94f5374fce5edbc8e2a8697c15331677e6ebf0b
    To:       7b65b75d204abed71587c9e519a89277766ee1d0
    Nonce:    1234
    GasPrice: 0x19
    GasLimit  0xf4240
    Value:    0xa
    Data:     0x31323334
    AccessList: [{0000000000000000000000000000000000000001 [0000000000000000000000000000000000000000000000000000000000000000]}]
    V:        0x1
    R:        0xbfc80a874c43b71b67c68fa5927d1443407f31aef4ec6369bbecdb76fc39b0c0
    S:        0x193e62c1dd63905aee7073958675dcb45d78c716a9a286b54a496e82cb762f26
    Hex:      7801f8a1028204d219830f4240947b65b75d204abed71587c9e519a89277766ee1d00a8431323334f838f7940000000000000000000000000000000000000001e1a0000000000000000000000000000000000000000000000000000000000000000001a0bfc80a874c43b71b67c68fa5927d1443407f31aef4ec6369bbecdb76fc39b0c0a0193e62c1dd63905aee7073958675dcb45d78c716a9a286b54a496e82cb762f26


```

### RPC Output (Example) <a href="#rpc-output-example" id="rpc-output-example"></a>

The following shows a transaction object returned via JSON RPC.

The return of `eth_getTransactionByHash`

```javascript
{
  "blockHash": "0x7bd7e8a92ecaa5781a15a8b6fff589f8ac8a79325b517a1ba5d5f2f3d7af1b00",
  "blockNumber": "0x1c8f4b",
  "from": "0x5618e15ec2916bbe6cf2cce20ce31e61d6062cac",
  "gas": "0x174876e800",
  "gasPrice": "0x5d21dba00",
  "hash": "0x3f67e48c2090f560234f555cd4edf7853b6327aa9a6a795be1efe3f360dac118",
  "input": "0x1122",
  "nonce": "0x11",
  "to": "0x5dce87b5bfcde54023811b168dc97a9f10913957",
  "transactionIndex": "0x0",
  "value": "0x186a0",
  "type": "0x1",
  "accessList": [
      {
          "address": "0x0000000000000000000000000000000000000001",
          "storageKeys": [
              "0x0000000000000000000000000000000000000000000000000000000000000000"
          ]
      }
  ],
  "chainId": "0x2710",
  "v": "0x1",
  "r": "0xebb2d2144293c257e27aaa1d22156f322b0d2d7385257f186c117899d791f174",
  "s": "0x5cea970287c9f0f9754050a552c458c066d8f3b3e4639f561b22ce4cb7553ac0"
}
```

The return of `klay_getTransactionByHash`

```javascript
{
  "accessList": [
      {
          "address": "0x0000000000000000000000000000000000000001",
          "storageKeys": [
              "0x0000000000000000000000000000000000000000000000000000000000000000"
          ]
      }
  ],
  "blockHash": "0x7bd7e8a92ecaa5781a15a8b6fff589f8ac8a79325b517a1ba5d5f2f3d7af1b00",
  "blockNumber": "0x1c8f4b",
  "chainID": "0x2710",
  "from": "0x5618e15ec2916bbe6cf2cce20ce31e61d6062cac",
  "gas": "0x174876e800",
  "gasPrice": "0x5d21dba00",
  "hash": "0x3f67e48c2090f560234f555cd4edf7853b6327aa9a6a795be1efe3f360dac118",
  "input": "0x1122",
  "nonce": "0x11",
  "senderTxHash": "0x3f67e48c2090f560234f555cd4edf7853b6327aa9a6a795be1efe3f360dac118",
  "signatures": [
      {
          "V": "0x1",
          "R": "0xebb2d2144293c257e27aaa1d22156f322b0d2d7385257f186c117899d791f174",
          "S": "0x5cea970287c9f0f9754050a552c458c066d8f3b3e4639f561b22ce4cb7553ac0"
      }
  ],
  "to": "0x5dce87b5bfcde54023811b168dc97a9f10913957",
  "transactionIndex": "0x0",
  "type": "TxTypeEthereumAccessList",
  "typeInt": 30721,
  "value": "0x186a0"
}
```

## TxTypeEthereumDynamicFee <a href="#txtypeethereumdynamicfee" id="txtypeethereumdynamicfee"></a>

`TxTypeEthereumDynamicFee` represents a type of Ethereum transaction specified in [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559). This transaction type contains `gasTipCap` and `gasFeeCap` instead of `gasPrice`. Since this transaction type exists to support compatibility, it only works with EOAs associated with \[AccountKeyLegacy]. EOAs associated with other account key types should use other transaction types such as `TxTypeValueTransfer`, `TxTypeSmartContractExecution`, and so on. This type of transaction can create accouns, transfer tokens, deploy/execute smart contracts, or a mix of the aforementioned.

{% hint style="success" %}
NOTE: Klaytn networks can process this transaction type after the `EthTxTypeCompatibleBlock`
{% endhint %}

{% hint style="success" %}
NOTE: Currently, this type of transaction only supports the format of the Ethereum transaction type. Unlike [EIP-2930](https://eips.ethereum.org/EIPS/eip-2930), there are no benefits in terms of transaction fees from using access list.
{% endhint %}

{% hint style="success" %}
NOTE: Since Klaytn has a fixed gas price, `gasTipCap` and `gasFeeCap` should take the gas price for the respective network, which is 250 ston at the time of writing.
{% endhint %}

### Attributes <a href="#attributes" id="attributes"></a>

| Attribute  | Type                  | Description                                                                                                                                                                                                                                                                                                  |
| ---------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| type       | uint8 (Go)            | The type of `TxTypeEthereumDynamicFee` that is a concatenation of `EthereumTxTypeEnvelope` and `EthereumTransactionType`. It must be `0x7802`.                                                                                                                                                               |
| chainId    | \*big.Int (Go)        | The destination chain ID.                                                                                                                                                                                                                                                                                    |
| nonce      | uint64 (Go)           | A value used to uniquely identify a sender’s transaction. If two transactions with the same nonce are generated by a sender, only one is executed.                                                                                                                                                           |
| gasTipCap  | \*big.Int (Go)        | A multiplier to get how much the sender will pay in addition to `baseFee`. Since Klaytn has a fixed gas price, `gasTipCap` and `gasFeeCap` should take the gas price for the respective network, which is 250 ston at the time of writing.                                                                   |
| gasFeeCap  | \*big.Int (Go)        | A multiplier to get how much the sender will pay in tokens. The amount of tokens the sender will pay is calculated via `gas` \* `gasFeeCap`. Since Klaytn has a fixed gas price, `gasTipCap` and `gasFeeCap` should take the gas price for the respective network, which is 250 ston at the time of writing. |
| gas        | uint64 (Go)           | The maximum amount of transaction fee the transaction is allowed to use.                                                                                                                                                                                                                                     |
| to         | \*common.Address (Go) | The account address that will receive the transferred value.                                                                                                                                                                                                                                                 |
| value      | \*big.Int (Go)        | The amount of KLAY in `peb` to be transferred.                                                                                                                                                                                                                                                               |
| data       | \[]byte (Go)          | Data attached to the transaction, used for transaction execution.                                                                                                                                                                                                                                            |
| accessList | type.AccessList (Go)  | A list of addresses and storage keys consisting of \[]\(common.Address, \[]common.Hash).                                                                                                                                                                                                                     |
| v, r, s    | \*big.Int (Go)        | The cryptographic signature generated by the sender to let the receiver obtain the sender's address.                                                                                                                                                                                                         |

### RLP Encoding for Signature <a href="#rlp-encoding-for-signature" id="rlp-encoding-for-signature"></a>

To make a signature for this transaction type, the RLP serialization proceeds as follows:

{% hint style="success" %}
NOTE: This type of transaction should be signed with London Signer
{% endhint %}

```javascript
SigRLP = EthereumTransactionType || encode([chainId, nonce, gasTipCap, gasFeeCap, gasLimit, to, value, data, accessList])
SigHash = keccak256(SigRLP)
Signature = sign(SigHash, <private key>)
```

### RLP Encoding for SenderTxHash <a href="#rlp-encoding-for-sendertxhash" id="rlp-encoding-for-sendertxhash"></a>

To obtain `SenderTxHash` for this transaction type, the RLP serialization proceeds as follows:

```javascript
SenderTxHashRLP = EthereumTransactionType || encode([chainId, nonce, gasTipCap, gasFeeCap, gasLimit, to, value, data, accessList, v, r, s])
SenderTxHash = keccak256(SenderTxHashRLP)
Signature = sign(SenderTxHash, <private key>)
```

### RLP Encoding for Transaction Hash <a href="#rlp-encoding-for-transaction-hash" id="rlp-encoding-for-transaction-hash"></a>

To obtain a transaction hash, the RLP serialization proceeds as follows:

```javascript
TxHashRLP = EthereumTransactionType || encode([chainId, nonce, gasTipCap, gasFeeCap, gasLimit, to, value, data, accessList, v, r, s])
TxHash = keccak256(TxHashRLP)
```

### Raw Transaction <a href="#raw-transaction" id="raw-transaction"></a>

```javascript
RawTx = EthereumTxTypeEnvelope || EthereumTransactionType || encode([chainId, nonce, gasTipCap, gasFeeCap, gasLimit, to, value, data, accessList, v, r, s])
```

### RLP Encoding (Example) <a href="#rlp-encoding-example" id="rlp-encoding-example"></a>

The following shows the result of the RLP serialization and the transaction object:

```javascript
    TX(be74e122acf00c2f257e8698ecf01140b58b2880de3f24d0875730425eccb45a)
    Contract: false
    Chaind:   0x2
    From:     a94f5374fce5edbc8e2a8697c15331677e6ebf0b
    To:       7b65b75d204abed71587c9e519a89277766ee1d0
    Nonce:    1234
    GasTipCap: 0x19
    GasFeeCap: 0x19
    GasLimit  0xf4240
    Value:    0xa
    Data:     0x31323334
    AccessList: [{0000000000000000000000000000000000000001 [0000000000000000000000000000000000000000000000000000000000000000]}]
    V:        0x0
    R:        0xca14aa0bada2da7ca1b143c16e2dd4a69f2a1e77ce54c7f6d440fe828a777f4f
    S:        0x117f0f78aed398b2995b5ee7c67ace25d52be3c72c1384c2aaa9683b351556
    Hex:      7802f8a1028204d21919830f4240947b65b75d204abed71587c9e519a89277766ee1d00a8431323334f838f7940000000000000000000000000000000000000001e1a0000000000000000000000000000000000000000000000000000000000000000080a0ca14aa0bada2da7ca1b143c16e2dd4a69f2a1e77ce54c7f6d440fe828a777f4f9f117f0f78aed398b2995b5ee7c67ace25d52be3c72c1384c2aaa9683b351556
```

### RPC Output (Example) <a href="#rpc-output-example" id="rpc-output-example"></a>

The following shows a transaction object returned via JSON RPC.

The return of `eth_getTransactionByHash`

```javascript
{
  "blockHash": "0x55792fe186e3d1515fe35a68c2c8d7977b2d7db184d80526f906c53222b77833",
  "blockNumber": "0x1c944d",
  "from": "0x5618e15ec2916bbe6cf2cce20ce31e61d6062cac",
  "gas": "0x174876e800",
  "gasPrice": "0x5d21dba00",
  "maxFeePerGas": "0x5d21dba00",
  "maxPriorityFeePerGas": "0x5d21dba00",
  "hash": "0x5db239963029ad9ef6c3331b10ae455638316e330b0efdae2cc1f8e86884e66e",
  "input": "0x1122",
  "nonce": "0x13",
  "to": "0xa0f1633f4c666d7fe5ba912bd5caf03d3655ac31",
  "transactionIndex": "0x0",
  "value": "0x186a0",
  "type": "0x2",
  "accessList": [
      {
          "address": "0x0000000000000000000000000000000000000001",
          "storageKeys": [
              "0x0000000000000000000000000000000000000000000000000000000000000000"
          ]
      }
  ],
  "chainId": "0x2710",
  "v": "0x1",
  "r": "0x27e007cbe79fd8cc9b89dd798bdd5aa62d038273bf006c7c3b40e13a938ab807",
  "s": "0x6209bb328855f02fa2671fecb41efd9f191b03ecab5e580227fa2a0674879384"
}
```

The return of `klay_getTransactionByHash`

```javascript
{
  "accessList": [
      {
          "address": "0x0000000000000000000000000000000000000001",
          "storageKeys": [
              "0x0000000000000000000000000000000000000000000000000000000000000000"
          ]
      }
  ],
  "blockHash": "0x55792fe186e3d1515fe35a68c2c8d7977b2d7db184d80526f906c53222b77833",
  "blockNumber": "0x1c944d",
  "chainId": "0x2710",
  "from": "0x5618e15ec2916bbe6cf2cce20ce31e61d6062cac",
  "gas": "0x174876e800",
  "hash": "0x5db239963029ad9ef6c3331b10ae455638316e330b0efdae2cc1f8e86884e66e",
  "input": "0x1122",
  "maxFeePerGas": "0x5d21dba00",
  "maxPriorityFeePerGas": "0x5d21dba00",
  "nonce": "0x13",
  "senderTxHash": "0x5db239963029ad9ef6c3331b10ae455638316e330b0efdae2cc1f8e86884e66e",
  "signatures": [
      {
          "V": "0x1",
          "R": "0x27e007cbe79fd8cc9b89dd798bdd5aa62d038273bf006c7c3b40e13a938ab807",
          "S": "0x6209bb328855f02fa2671fecb41efd9f191b03ecab5e580227fa2a0674879384"
      }
  ],
  "to": "0xa0f1633f4c666d7fe5ba912bd5caf03d3655ac31",
  "transactionIndex": "0x0",
  "type": "TxTypeEthereumDynamicFee",
  "typeInt": 30722,
  "value": "0x186a0"
}
```


# 연산


# 클레이튼 스마트 컨트랙트

Klaytn 스마트 컨트랙트는 비즈니스 로직, 게임, 라이브러리, 토큰 전송 등 Klaytn 블록체인과 상호 작용하는 모든 유형의 코드를 실행하는 프로그램입니다. 스마트 컨트랙트에 쓰여있는 조건이 충족되면 컨트랙트는 즉시 실행됩니다. 스마트 컨트랙트 내의 조건은 프로그래밍 언어로 쓰여있습니다. 컨트랙트의 데이터는 상태(state)로 저장되어 있습니다.

Klaytn은 Klaytn 네트워크에서 스마트 컨트랙트를 작성하고 실행하는 몇 가지 방법을 제공합니다. 첫째, Klaytn은 솔리디티(solidity)를 지원하고 Remix 또는 트러플과 같은 이더리움 개발 툴킷과의 상호운용성을 가지고 있습니다. 솔리디티로 작성된 스마트 컨트랙트는 기존 솔리디티 컴파일러를 사용하여 컴파일하고 추가 작업없이 Klaytn에서 실행할 수 있습니다. Solidity는 이더리움의 사실상 표준 컨트랙트 프로그래밍 언어이며 활발한 커뮤니티를 가지고 있습니다. 따라서, Klaytn은 개발자에게 가장 친숙한 개발 환경을 제공하여 이더리움 Dapp 개발자들이 쉽게 그들의 작업을 Klaytn으로 마이그레이션 할 수 있도록 솔리디티를 지원합니다.

미래에 Klaytn은 다양한 프로그래밍 언어로 작성된 스마트 컨트랙트를 수용할 예정입니다. 그래서 더 광범위한 개발자를 지원하고, 그들이 가장 친숙한 개발 환경에서 개발할 수 있도록 만들 예정입니다. 앞으로 Klaytn은 개발자가 흥미로워하는 다양한 프로그래밍 언어를 계속 찾아나갈 것입니다.

## 경제적인 스마트 컨트랙트 실행 비용 <a href="#affordable-smart-contract-execution-cost" id="affordable-smart-contract-execution-cost"></a>

스마트 컨트랙트 실행에 수수료를 청구하는 이유 중 한 가지는 잘못되었거나 악의적으로 작성된 컨트랙트가 실행되지 않도록 만들어 제한된 자원을 효율적으로 활용하기 위해서입니다. 즉, 블록체인은 (1)개발자들이 효율적으로 코드를 작성하게 만들고, (2) 악의적인 공격자가 공격했을 때 얻을 수 있는 경제적 이득을 줄이기 위해서 스마트 컨트랙트를 실행하는 데 소모되는 비용을 고의로 늘립니다. 이에 알맞는 전략은 정상적인 실행에는 비용을 적게 청구하고 악의적인 실행에는 많이 청구해야 합니다. 이더리움의 Opcode 기반 수수료 모델은 자원 낭비를 방지하는 데 유용하지만, 일부 Opcode(예: state write)의 높은 가스 가격 때문에 일반적인 스마트 컨트랙트도 실행하기 힘들게 만들 수 있습니다. 이는 블록체인 기술의 대중화를 막습니다. To address this problem, Klaytn plans to use an opcode-based fixed fee model with low unit cost per opcode. This is made possible by dramatically increasing scalability of blockchain protocol.

Opcode cost is directly related to the amount of resources that the platform can use. The Ethereum state write cost is high since the storage, and the network bandwidth required to record and propagate the changed states are limited. Conversely, if a blockchain has abundant resources (e.g., CPU time, storage, network bandwidth), then the unit cost per opcode can be substantially lower than that of Ethereum, and the cost difference between opcodes can be minimized. Klaytn aims to lower opcode unit cost by vertically scaling each CN node (i.e., acquiring high-end hardware), parallelizing computation (i.e., logical scaling via service chain), and horizontally scaling physical clusters.


# 실행 모델(Execution Model)

This page describes the execution model, the data structures, and the life cycle of Klaytn smart contracts.

## Execution Model <a href="#execution-model" id="execution-model"></a>

Transactions can be generated by platform APIs as described in [Platform API Specification](/content/dapp/json-rpc/api-references). 이 트랜잭션들은 블록에 저장되기 위해 \_컨센서스 노드 (CNs)\_로 보내집니다. CN은 전송된 각 트랜잭션이 유효한지 검사합니다. 유효한 트랜잭션은 트랜잭션 풀에 저장되고, 그렇지 않다면 버려집니다. CN은 트랜잭션 풀에서 현재 블록에서 실행 가능한 트랜잭션을 선택하고, 하나씩 실행합니다.

트랜잭션을 실행하려면 발신자가 일정량의 KLAY를 트랜잭션 수수료로 지불해야합니다. 트랜잭션 수수료는 사용된 가스와 단가(unit price)를 기준으로 계산됩니다. 가스는 연산의 기본적인 단위입니다. Klaytn 노드에서 실행되는 모든 연산은 미리 정의된 양의 가스를 소모합니다. 트랜잭션에 필요한 정확한 KLAY 양은 [트랜잭션 수수료](/content/klaytn/design/transaction-fees)에 설명된 공식으로 계산됩니다. 트랜잭션이 충분한 가스와 함께 보내지지 않는다면 트랜잭션은 실행되지 않습니다. 또한, 발신인의 잔고가 부족할 때도 트랜잭션이 보내지지 않습니다.

트랜잭션이 성공적으로 실행되면, 트랜잭션은 현재 블록에 담기게 됩니다. CN은 블록 가스 한도나 블록 생성 제한 시간에 도달할 때까지 트랜잭션을 모읍니다. 그 후, CN은 트랜잭션이 담긴 블록을 생성합니다. 이 단계에서는 블록의 여러 필드를 채워 넣어야합니다. 예를 들어 트랜잭션, 영수증, 상태 등의 해시를 계산해야 합니다. 채워야하는 모든 필드가 채워지면 CN은 블록 해시를 생성합니다.

블록 생성이 끝나면 블록은 다른 모든 CN들로 전파됩니다. 다른 모든 CN들은 전파된 블록을 검증하고 BFT 합의 알고리즘을 이용하여 검증 결과에 대한 합의에 도달합니다. 필요 숫자 이상의 CN이 검증 과정을 성공적으로 마치면 블록이 블록체인에 저장됩니다. BFT합의 알고리즘은 즉각적인 완결성(immediate finality)을 특성으로 가지므로, 블록은 완결되고 절대 삭제되지 않습니다. 블록이 완결되고 나면 블록의 모든 트랜잭션은 되돌릴 수 없고, 트랜잭션 결과는 발신자가 요청시 리턴됩니다.

### 트랜잭션 실행에 관한 제한 사항 <a href="#restrictions-on-transaction-execution" id="restrictions-on-transaction-execution"></a>

Klaytn의 Baobab 및 Cypress 네트워크에는 현재 트랜잭션 실행에 관해 다음과 같은 제한이 있습니다.

* A transaction must set its gas price to Klaytn's [unit price](/content/klaytn/design/klaytn-native-coin-klay#units-of-klay), *i.e.*, 250 ston.
* 연산 비용 한도보다 실행 비용이 큰 트랜잭션은 버려집니다. [연산 비용](/content/klaytn/design/computation/computation-cost)을 참고해주세요.

## 데이터 구조(Data Structures) <a href="#data-structures" id="data-structures"></a>

### Account <a href="#account" id="account"></a>

Klaytn의 계정(account)은 개인의 잔액이나 스마트 컨트랙트에 관한 정보를 포함하는 데이터 구조입니다. Klaytn은 계정 모델을 재설계하여 더 나은 DX 및 UX를 제공하도록 만들었습니다. 계정 모델에 대한 자세한 정보는 [여기](/content/klaytn/design/accounts)서 찾을 수 있습니다.

### Transaction <a href="#transaction" id="transaction"></a>

블록체인 플랫폼의 트랜잭션은 블록체인의 상태를 변경하는 노드간 전송되는 메시지입니다. Klaytn은 트랜잭션 모델 또한 재설계했습니다. 성능을 최적화하고, 새로 설계된 계정 모델을 지원할 수 있도록 트랜잭션의 목적에 따라 트랜잭션은 여러 종류로 분류되어 있습니다. 계정 모델에 대한 자세한 정보는 [여기](/content/klaytn/design/transactions)서 찾을 수 있습니다.

### 상태(State) <a href="#state" id="state"></a>

Klaytn의 **상태**는 계정 상태를 모은 것입니다. Klaytn의 노드들이 같은 블록들을 같은 순서대로 처리했다면 상태는 Klaytn 네트워크의 모든 노드에서 동일해야 합니다. 상태는 Klaytn 노드에서 트랜잭션이 실행될 때 변경됩니다.

아래 표는 상태에 저장된 계정 데이터를 보여줍니다.

| 구성요소        | Description                                                                                                                                         |
| ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| nonce       | 계정에서 실행한 트랜잭션의 수를 나타내는 정숫값입니다. 트랜잭션을 보낼 때 트랜잭션의 논스는 계정의 논스와 같아야합니다.                                                                                 |
| balance     | 계정이 현재 가지고 있는 KLAY를 나타내는 양의 정숫값입니다.                                                                                                                 |
| storageRoot | A 256-bit hash of the root of the Merkle Patricia Trie that contains the values of all the storage variables in the account.                        |
| codeHash    | 계정 바이트코드의 해시입니다. This value is immutable, which means it is set only when the smart contract is created. 계정이 EOA 또는 EA인 경우, 이 값은 null의 해시값으로 설정됩니다. |

### Block <a href="#block" id="block"></a>

블록체인은 문자 그대로 블록을 체인으로 연결한 것이기 때문에 블록은 Klaytn 블록체인의 아주 중요한 요소입니다. 아래 표는 블록의 구성 요소를 보여줍니다.

| Component        | Description                                                                                                         |
| ---------------- | ------------------------------------------------------------------------------------------------------------------- |
| baseFeePerGas    | The base fee per gas. This value is returned only when EthTxTypeCompatibleBlock is activated for that block number. |
| blockScore       | Former difficulty. Always 1 in the BFT consensus engine                                                             |
| extraData        | The "extra data" field of this block.                                                                               |
| gasUsed          | The total used gas by all transactions in this block.                                                               |
| governanceData   | RLP encoded governance configuration                                                                                |
| logsBloom        | The bloom filter for the logs of the block. `null` when it is pending block.                                        |
| number           | The block number. `null` when it is pending block.                                                                  |
| parentHash       | The hash of the block's parent block.                                                                               |
| proposer         | The address of the block proposer.                                                                                  |
| receiptsRoot     | The root of the receipts trie of the block.                                                                         |
| reward           | The address receiving block reward.                                                                                 |
| size             | Integer the size of this block in bytes.                                                                            |
| stateRoot        | The root of the final state trie of the block.                                                                      |
| totalBlockScore  | Integer of the total blockScore of the chain until this block.                                                      |
| transactionsRoot | The root of the transaction trie of the block.                                                                      |
| timestamp        | The Unix timestamp for when the block was collated.                                                                 |
| timestampFoS     | The fraction of a second of the timestamp for when the block was collated.                                          |
| transactions     | Array of transaction objects, or 32-byte transaction hashes depending on the last given parameter.                  |
| voteData         | RLP encoded governance vote of the proposer                                                                         |

## Smart Contract <a href="#smart-contract" id="smart-contract"></a>

\_스마트 컨트랙트\_는 Klaytn 블록체인의 특정 주소에 있는 코드(functions)와 데이터 (state)의 모음입니다. 컨트랙트 계정은 실질적으로 튜링 완전한 연산을 수행할 뿐만 아니라 서로 간에 메시지를 전달할 수 있습니다. 스마트 컨트랙트는 블록체인 상에 클레이튼 고유의 바이너리 형식으로 존재합니다. 현재 Klaytn은 한가지 바이너리 형식(Ethereum Virtual Machine (EVM) 바이트 코드)을 지원합니다. 하지만 미래에는 다른 형식들도 지원될 예정입니다.

### 스마트 컨트랙트 생성 <a href="#creating-smart-contracts" id="creating-smart-contracts"></a>

빈 주소로 바이너리 데이터를 트랜잭션에 담아 보내면 Klaytn 블록체인에 스마트 컨트랙트가 생성됩니다. 바이너리 데이터는 여러 형식으로 존재할 수 있지만, Klaytn에서는 현재 EVM 바이트코드 한 가지만을 지원합니다. 트랜잭션을 실행하기 위해서는 수수료를 지불해야한다는 사실도 기억해주세요. 블록에 트랜잭션이 저장된 후, 발신자의 계정 잔고는 트랜잭션 수수료 모델에 따라서 줄어듭니다. 일정 시간이 지나면 트랙잭션을 블록에서 확인할 수 있으며 이는 트랜잭션 상태가 합의에 도달했음을 알려줍니다. 이 시점부터 스마트 컨트랙트는 Klaytn 블록체인 상에 존재하게 됩니다. As [eip-3541](https://eips.ethereum.org/EIPS/eip-3541) is brought at the Kore hardfork, deployment of a new code starting with the 0xEF byte is not allowed.

### 스마트 컨트랙트 실행 <a href="#executing-smart-contracts" id="executing-smart-contracts"></a>

스마트 컨트랙트의 함수는 스마트 컨트랙트에 트랜잭션을 보내거나 노드에서 로컬로 함수를 호출하여 실행할 수 있습니다. 트랜잭션을 보내 함수가 호출되면, 트랜잭션을 처리하여 함수가 실행됩니다. 트랜잭션을 보내면 Klay가 소모되며, 이 호출은 블록체인 상에 영원히 기록됩니다. 이런 호출의 리턴 값은 트랜잭션의 해시입니다. 로컬에서 함수가 호출되면 Klaytn 가상머신 (KLVM)에서 로컬로 실행되며, 함수의 리턴값을 반환합니다. 이런 호출은 블록체인 상에 기록되지 않습니다. 따라서 스마트 컨트랙트의 내부 상태를 바꾸지 않습니다. 이런 종류의 호출은 상수 함수 호출(constant function call)이라고 합니다. 이런 호출은 Klay를 소모하지 않습니다. 상수 함수 호출(constant function call)은 오직 리턴값만 필요할 때 사용하고, 컨트랙트 상태의 부작용(side effect)에 관심이 있으면 트랜잭션을 사용하시면 됩니다.

### 스마트 컨트랙트 비활성화 <a href="#disabling-smart-contracts" id="disabling-smart-contracts"></a>

스마트 컨트랙트는 Klaytn 블록체인 상에 존재하기 때문에 삭제될 수 없습니다. 오직 비활성화 될 수만 있습니다. 현재 Klaytn 스마트 컨트랙트를 비활성화기 위해서는 이더리움에서 사용된 방식과 같은 방식을 이용할 수 있습니다. 예를 들어, Klaytn 스마트 컨트랙트는 솔리디티의 [`selfdestruct(address recipient)`](https://solidity.readthedocs.io/en/v0.5.6/introduction-to-smart-contracts.html#self-destruct) 호출이나 (the KLVM opcode `SELFDESTRUCT`)을 이용하여 비활성화 될 수 있습니다. Klaytn팀은 다른 실행 환경에서 스마트 컨트랙트를 비활성화하는 방법도 제공할 예정입니다.

### 스마트 컨트랙트 업그레이드 <a href="#upgrading-smart-contracts" id="upgrading-smart-contracts"></a>

Klaytn은 현존하는 블록체인의 불편한 사용자 경험 문제를 해결하기 위해 배포된 스마트 컨트랙트를 업그레이드 할 수 있는 방법들을 제공할 것입니다. 예를 들어, 블록체인 상에 배포된 서비스는 업그레이드하기 힘듭니다. Klaytn은 프레임워크와 스마트 컨트랙트 라이브러리를 제공하여 서비스 제공자(SPs)가 배포된 서비스를 업그레이드하고, 서비스 정보를 옮길 수 있도록 할 예정입니다. Klatn은 다음 요구사항들을 고려하여 신중히 이 기능을 제공할 것입니다.

* 승인된 계정 또는 스마트 컨트랙트 소유자만 스마트 컨트랙트를 업그레이드 할 수 있어야 합니다.
* 업그레이드된 스마트 컨트랙트는 기존 스마트 컨트랙트가 관리하는 기존 데이터를 조작할 수 있어야 합니다.
* 기존 스마트 컨트랙트를 참고하는 다른 스마트 컨트랙트는 새롭게 업그레이드된 스마트 컨트랙트를 이용할지 결정할 수 있어야 합니다.


# Computation Cost

Since Klaytn aims to maintain 1-second block time, the execution time of transactions has to be managed. Here are three approaches to achieve that:

1. Limiting the gas limit of a transaction
2. Limiting the execution time of a transaction
3. Limiting the computation cost of a transaction

Limiting the gas limit of a transaction was not a feasible solution because the concept of the gas represents the current exchange value of the various resources in the blockchain platform such as computation, storage, network bandwidth, and so on. It is not suitable as a metric for the transaction execution time.

Limiting the execution time of a transaction was not feasible either because the execution time can vary between nodes on the blockchain platform. For example, consider the case in which we limit the execution time of a transaction to be 100 milli-second. If a node executes a transaction in 90 ms and another node executes it in 110 ms, the two nodes cannot reach a consensus. Hence, this solution is not appropriate.

The last approach is to limit the computation cost of a transaction. We modelled the computation cost of each EVM opcode based on its actual execution time and limit the sum of computation cost of a transaction. With this approach, we eliminate other factors and only count the normalized execution time unit, and nodes can reach a consensus as well.

Therefore, we chose the third option for Klaytn. For now, the limit of the execution cost is set to 100,000,000. Since the limit is determined by the platform, developers should be aware of the computation cost of a transaction. To calculate the computation cost of a transaction, Klaytn provides [klay\_estimateComputationCost](/content/dapp/json-rpc/api-references/klay/transaction#klay_estimatecomputationcost). The usage is almost the same as [klay\_estimateGas](/content/dapp/json-rpc/api-references/klay/transaction#klay_estimategas).

## Computation Cost of Opcodes <a href="#computation-cost-of-opcodes" id="computation-cost-of-opcodes"></a>

The below table shows the computation cost of EVM opcodes. The computation cost was determined based on experiments.

{% hint style="success" %}
NOTE: Computation costs have changed with the `Kore` hardfork. 이전 문서는 [이전 문서](/content/klaytn/design/computation/computation-cost/computation-cost-previous)를 참고해주세요.

`Kore` hardfork block numbers are as follows.

* Baobab Testnet: `#111736800`
* Cypress Mainnet: `#119750400`
  {% endhint %}

| Opcode         | ComputationCost |
| -------------- | --------------: |
| STOP           |               0 |
| ADD            |             150 |
| MUL            |             200 |
| SUB            |             219 |
| DIV            |             404 |
| SDIV           |             739 |
| MOD            |             812 |
| SMOD           |             560 |
| ADDMOD         |            1410 |
| MULMOD         |            1760 |
| EXP            |            5000 |
| SIGNEXTEND     |             481 |
| LT             |             201 |
| GT             |             264 |
| SLT            |             176 |
| SGT            |             222 |
| EQ             |             220 |
| ISZERO         |             165 |
| AND            |             288 |
| OR             |             160 |
| XOR            |             454 |
| NOT            |             364 |
| BYTE           |             589 |
| SHL            |             478 |
| SHR            |             498 |
| SAR            |             834 |
| SHA3           |            2465 |
| ADDRESS        |             284 |
| BALANCE        |            1407 |
| ORIGIN         |             210 |
| CALLER         |             188 |
| CALLVALUE      |             149 |
| CALLDATALOAD   |             596 |
| CALLDATASIZE   |             194 |
| CALLDATACOPY   |             100 |
| CODESIZE       |             145 |
| CODECOPY       |             898 |
| GASPRICE       |             131 |
| EXTCODESIZE    |            1481 |
| EXTCODECOPY    |            1000 |
| RETURNDATASIZE |              10 |
| RETURNDATACOPY |              40 |
| EXTCODEHASH    |            1000 |
| BLOCKHASH      |             500 |
| COINBASE       |             189 |
| TIMESTAMP      |             265 |
| NUMBER         |             202 |
| PREVRANDAO     |            1498 |
| GASLIMIT       |             166 |
| CHAINID        |             120 |
| SELFBALANCE    |             374 |
| POP            |             140 |
| MLOAD          |             376 |
| MSTORE         |             288 |
| MSTORE8        |            5142 |
| SLOAD          |             835 |
| SSTORE         |            1548 |
| JUMP           |             253 |
| JUMPI          |             176 |
| PC             |             147 |
| MSIZE          |             137 |
| GAS            |             230 |
| JUMPDEST       |              10 |
| PUSH0          |              80 |
| PUSH1          |             120 |
| PUSH2          |             120 |
| PUSH3          |             120 |
| PUSH4          |             120 |
| PUSH5          |             120 |
| PUSH6          |             120 |
| PUSH7          |             120 |
| PUSH8          |             120 |
| PUSH9          |             120 |
| PUSH10         |             120 |
| PUSH11         |             120 |
| PUSH12         |             120 |
| PUSH13         |             120 |
| PUSH14         |             120 |
| PUSH15         |             120 |
| PUSH16         |             120 |
| PUSH17         |             120 |
| PUSH18         |             120 |
| PUSH19         |             120 |
| PUSH20         |             120 |
| PUSH21         |             120 |
| PUSH22         |             120 |
| PUSH23         |             120 |
| PUSH24         |             120 |
| PUSH25         |             120 |
| PUSH26         |             120 |
| PUSH27         |             120 |
| PUSH28         |             120 |
| PUSH29         |             120 |
| PUSH30         |             120 |
| PUSH31         |             120 |
| PUSH32         |             120 |
| DUP1           |             190 |
| DUP2           |             190 |
| DUP3           |             176 |
| DUP4           |             142 |
| DUP5           |             177 |
| DUP6           |             165 |
| DUP7           |             147 |
| DUP8           |             157 |
| DUP9           |             138 |
| DUP10          |             174 |
| DUP11          |             141 |
| DUP12          |             144 |
| DUP13          |             157 |
| DUP14          |             143 |
| DUP15          |             237 |
| DUP16          |             149 |
| SWAP1          |             141 |
| SWAP2          |             156 |
| SWAP3          |             145 |
| SWAP4          |             135 |
| SWAP5          |             115 |
| SWAP6          |             146 |
| SWAP7          |             199 |
| SWAP8          |             130 |
| SWAP9          |             160 |
| SWAP10         |             134 |
| SWAP11         |             147 |
| SWAP12         |             128 |
| SWAP13         |             121 |
| SWAP14         |             114 |
| SWAP15         |             197 |
| SWAP16         |             128 |
| LOG0           |             100 |
| LOG1           |            1000 |
| LOG2           |            1000 |
| LOG3           |            1000 |
| LOG4           |            1000 |
| PUSH           |               0 |
| DUP            |               0 |
| SWAP           |               0 |
| CREATE         |            2094 |
| CALL           |            5000 |
| CALLCODE       |            4000 |
| RETURN         |               0 |
| DELEGATECALL   |             696 |
| CREATE2        |           10000 |
| STATICCALL     |           10000 |
| REVERT         |               0 |
| SELFDESTRUCT   |               0 |
| BASEFEE        |             198 |


# 연산 비용 (구 버전 문서)

Klaytn은 1초 블록생성 시간을 목표로 하기 때문에 트랜잭션 실행 시간이 관리되어야 합니다. 이를 위한 3가지 접근법이 있습니다.

1. Limiting the gas limit of a transaction
2. Limiting the execution time of a transaction
3. Limiting the computation cost of a transaction

그러나, 가스 한도를 제한하는 것은 실현 가능한 해결책이 아닙니다. 블록체인 플랫폼에서 연산, 저장공간, 네트워크 대역폭 등 여러 자원의 교환 값을 나타내는 것이 가스의 개념이기 때문입니다. 따라서, 트랜잭션 실행 시간을 관리하기 위한 방법으로는 적합하지 않습니다.

트랜잭션의 실행 시간을 제한하는 것도 실현 가능한 해결책이 아닙니다. 실행 시간은 블록체인 플랫폼 내 노드에 따라 달라질 수 있기 때문입니다. 예를 들어, 트랜잭션 실행 시간을 100ms로 제한하는 경우를 고려해보겠습니다. 만약 한 노드에서 트랜잭션 실행 시간이 90ms고, 다른 노드에서 110ms라면 두 노드는 합의에 도달 할 수 없습니다. 그렇기 때문에 이 해결책은 적절하지 않습니다.

마지막 방법은 트랜잭션의 연산 비용을 제한하는 것입니다. 우리는 각 EVM 연산자(Opcode)의 연산 비용을 실제 실행 시간에 기반하여 모델링하고, 한 트랜잭션 연산 비용의 합계를 제한합니다. 이 접근 방식을 사용하면 다른 요소들을 제거하고, 정규화된 실행 시간만 계산하여 노드들이 합의에 도달 할 수 있습니다.

그렇기 때문에 우리는 Klaytn에 세번 째 방법을 선택했습니다. 현재는 실행 비용 한도는 100,000,000으로 설정되어 있습니다. 한도는 플랫폼에 의해 결정되므로 개발자들은 트랜잭션의 연산 비용을 알아야합니다. To calculate the computation cost of a transaction, Klaytn provides [klay\_estimateComputationCost](/content/dapp/json-rpc/api-references/klay/transaction#klay_estimateComputationCost). The usage is almost the same as [klay\_estimateGas](/content/dapp/json-rpc/api-references/klay/transaction#klay_estimateGas).

## Opcode의 연산 비용 <a href="#computation-cost-of-opcodes" id="computation-cost-of-opcodes"></a>

아래 표는 EVM Opcode의 연산 비용을 보여줍니다. 연산 비용은 시뮬레이션을 통해 결정되었습니다.

{% hint style="success" %}
참고: 이 문서에는 프로토콜 업데이트 적용 이전에 사용되던 연산 비용이 포함되어 있습니다. 최신 문서는 [최신 문서](/content/klaytn/design/computation/computation-cost)를 참고해주세요.
{% endhint %}

| Opcode         | 연산 비용 |
| -------------- | ----: |
| STOP           |     0 |
| ADD            |   150 |
| MUL            |   200 |
| SUB            |   219 |
| DIV            |   404 |
| SDIV           |   739 |
| MOD            |   812 |
| SMOD           |   560 |
| ADDMOD         |  3349 |
| MULMOD         |  4757 |
| EXP            |  5000 |
| SIGNEXTEND     |   481 |
| LT             |   201 |
| GT             |   264 |
| SLT            |   176 |
| SGT            |   222 |
| EQ             |   220 |
| ISZERO         |   165 |
| AND            |   288 |
| OR             |   160 |
| XOR            |   657 |
| NOT            |  1289 |
| BYTE           |   589 |
| SHL            |  1603 |
| SHR            |  1346 |
| SAR            |  1815 |
| SHA3           |  2465 |
| ADDRESS        |   284 |
| BALANCE        |  1407 |
| ORIGIN         |   210 |
| CALLER         |   188 |
| CALLVALUE      |   149 |
| CALLDATALOAD   |   596 |
| CALLDATASIZE   |   194 |
| CALLDATACOPY   |   100 |
| CODESIZE       |   145 |
| CODECOPY       |   898 |
| GASPRICE       |   131 |
| EXTCODESIZE    |  1481 |
| EXTCODECOPY    |  1000 |
| RETURNDATASIZE |    10 |
| RETURNDATACOPY |    40 |
| EXTCODEHASH    |  1000 |
| BLOCKHASH      |   500 |
| COINBASE       |   189 |
| TIMESTAMP      |   265 |
| NUMBER         |   202 |
| DIFFICULTY     |   180 |
| GASLIMIT       |   166 |
| POP            |   140 |
| MLOAD          |   376 |
| MSTORE         |   288 |
| MSTORE8        |  5142 |
| SLOAD          |   835 |
| SSTORE         |  1548 |
| JUMP           |   253 |
| JUMPI          |   176 |
| PC             |   147 |
| MSIZE          |   137 |
| GAS            |   230 |
| JUMPDEST       |    10 |
| PUSH1          |   120 |
| PUSH2          |   120 |
| PUSH3          |   120 |
| PUSH4          |   120 |
| PUSH5          |   120 |
| PUSH6          |   120 |
| PUSH7          |   120 |
| PUSH8          |   120 |
| PUSH9          |   120 |
| PUSH10         |   120 |
| PUSH11         |   120 |
| PUSH12         |   120 |
| PUSH13         |   120 |
| PUSH14         |   120 |
| PUSH15         |   120 |
| PUSH16         |   120 |
| PUSH17         |   120 |
| PUSH18         |   120 |
| PUSH19         |   120 |
| PUSH20         |   120 |
| PUSH21         |   120 |
| PUSH22         |   120 |
| PUSH23         |   120 |
| PUSH24         |   120 |
| PUSH25         |   120 |
| PUSH26         |   120 |
| PUSH27         |   120 |
| PUSH28         |   120 |
| PUSH29         |   120 |
| PUSH30         |   120 |
| PUSH31         |   120 |
| PUSH32         |   120 |
| DUP1           |   190 |
| DUP2           |   190 |
| DUP3           |   176 |
| DUP4           |   142 |
| DUP5           |   177 |
| DUP6           |   165 |
| DUP7           |   147 |
| DUP8           |   157 |
| DUP9           |   138 |
| DUP10          |   174 |
| DUP11          |   141 |
| DUP12          |   144 |
| DUP13          |   157 |
| DUP14          |   143 |
| DUP15          |   237 |
| DUP16          |   149 |
| SWAP1          |   141 |
| SWAP2          |   156 |
| SWAP3          |   145 |
| SWAP4          |   135 |
| SWAP5          |   115 |
| SWAP6          |   146 |
| SWAP7          |   199 |
| SWAP8          |   130 |
| SWAP9          |   160 |
| SWAP10         |   134 |
| SWAP11         |   147 |
| SWAP12         |   128 |
| SWAP13         |   121 |
| SWAP14         |   114 |
| SWAP15         |   197 |
| SWAP16         |   128 |
| LOG0           |   100 |
| LOG1           |  1000 |
| LOG2           |  1000 |
| LOG3           |  1000 |
| LOG4           |  1000 |
| PUSH           |     0 |
| DUP            |     0 |
| SWAP           |     0 |
| CREATE         |  2094 |
| CALL           |  5000 |
| CALLCODE       |  4000 |
| RETURN         |     0 |
| DELEGATECALL   |   696 |
| CREATE2        | 10000 |
| STATICCALL     | 10000 |
| REVERT         |     0 |
| SELFDESTRUCT   |     0 |


# Klaytn 가상머신

{% hint style="success" %}
NOTE: KLVM has changed with the `Kore` hardfork. If you want the previous document, please refer to [previous document](/content/klaytn/design/computation/klaytn-virtual-machine/klaytn-virtual-machine-previous).

`Kore` hardfork block numbers are as follows.

* Baobab Testnet: `#111736800`
* Cypress Mainnet: `#119750400`
  {% endhint %}

## Overview <a href="#overview" id="overview"></a>

The current version of the Klaytn Virtual Machine (KLVM) is derived from the Ethereum Virtual Machine (EVM). The content of this chapter is based primarily on the [Ethereum Yellow Paper](https://github.com/ethereum/yellowpaper). KLVM is continuously being improved by the Klaytn team, thus this document could be updated frequently. Please do not regard this document as the final version of the KLVM specification. As described in the Klaytn position paper, the Klaytn team also plans to adopt other virtual machines or execution environments in order to strengthen the capability and performance of the Klaytn platform. This chapter presents a specification of KLVM and the differences between KLVM and EVM.

KLVM is a virtual state machine that formally specifies Klaytn's execution model. The execution model specifies how the system state is altered given a series of bytecode instructions and a small tuple of environmental data. KLVM is a quasi-Turing-complete machine; the *quasi* qualification stems from the fact that the computation is intrinsically bounded through a parameter, *gas*, which limits the total amount of computation performed.

KLVM executes Klaytn virtual machine code (or Klaytn bytecode) which consists of a sequence of KLVM instructions. The KLVM code is the programming language used for accounts on the Klaytn blockchain that contain code. The KLVM code associated with an account is executed every time a message is sent to that account; this code has the ability to read/write from/to storage and send messages.

## KLVM Specification <a href="#klvm-specification" id="klvm-specification"></a>

### Conventions <a href="#conventions" id="conventions"></a>

We use the following notations and conventions in this document.

* `A := B`
  * `:=` is used to define `A` as `B`.
* We use the terms "smart contract" and "contract" interchangeably.
* We use the terms "opcode" as the "operation code/operation"

### Symbols <a href="#symbols" id="symbols"></a>

The following tables summarize the symbols used in the KLVM specification.

#### Blockchain-Related Symbols <a href="#blockchain-related-symbols" id="blockchain-related-symbols"></a>

| Symbol     | Description                           |
| ---------- | ------------------------------------- |
| `BC`       | Blockchain                            |
| `B`        | Block                                 |
| `B_header` | The block header of the present block |

#### State-Related Symbols <a href="#state-related-symbols" id="state-related-symbols"></a>

| Symbol           | Description                                |
| ---------------- | ------------------------------------------ |
| `S`              | State                                      |
| `S_system`       | System state                               |
| `S_machine`      | Machine state                              |
| `P_modify_state` | The permission to make state modifications |

#### Transaction-Related Symbols <a href="#transaction-related-symbols" id="transaction-related-symbols"></a>

| Symbol    | Description                                                                                                                                              |
| --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `T`       | Transaction                                                                                                                                              |
| `T_code`  | A byte array containing machine code to be executed                                                                                                      |
| `T_data`  | A byte array containing the input data to the execution; if the execution agent is a transaction, this would be the transaction data.                    |
| `T_value` | A value, in peb, passed to the account as part of the execution procedure; if the execution agent is a transaction, this would be the transaction value. |
| `T_depth` | The depth of the present message-call or contract-creation stack (*i.e.*, the number of `CALL`s or `CREATE`s being executed at present)                  |

#### Gas-Related Symbols <a href="#gas-related-symbols" id="gas-related-symbols"></a>

| Symbol    | Description                                                       |
| --------- | ----------------------------------------------------------------- |
| `G`       | Gas                                                               |
| `G_rem`   | Remaining gas for computation                                     |
| `G_price` | The price of gas in the transaction that originated the execution |

#### Address-Related Symbols <a href="#address-related-symbols" id="address-related-symbols"></a>

| Symbol            | Description                                                                                                                              |
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `A`               | Address                                                                                                                                  |
| `A_code_owner`    | The address of the account that owns the executing code                                                                                  |
| `A_tx_sender`     | The sender address of the transaction that originated the current execution                                                              |
| `A_code_executor` | the address of the account that initiated code execution; if the execution agent is a transaction, this would be the transaction sender. |

#### Functions <a href="#functions" id="functions"></a>

|   Symbol  | Description                                                                                                   |
| :-------: | ------------------------------------------------------------------------------------------------------------- |
| `F_apply` | A function that applies a transaction with input to a given state and returns the resultant state and outputs |

### Basics <a href="#basics" id="basics"></a>

KLVM is a simple stack-based architecture. The word size of the machine (and thus the size of stack items) is 256-bit. This was chosen to facilitate the Keccak-256 hash scheme and the elliptic-curve computations. The memory model is a simple word-addressed byte array. The stack has a maximum size of 1024. The machine also has an independent storage model; this is similar in concept to the memory but rather than a byte array, it is a word-addressable word array. Unlike memory, which is volatile, storage is nonvolatile and is maintained as part of the system state. All locations in both storage and memory are initially well-defined as zero.

The machine does not follow the standard von Neumann architecture. Rather than storing program code in generally accessible memory or storage, code is stored separately in virtual read-only memory and can be interacted with only through specialized instructions.

The machine can execute exception code for several reasons, including stack underflows and invalid instructions. Similar to an out-of-gas exception, these exceptions do not leave state changes intact. Rather, the virtual machine halts immediately and reports the issue to the execution agent (either the transaction processor or, recursively, the spawning execution environment), which will be addressed separately.

### Fees Overview <a href="#fees-overview" id="fees-overview"></a>

Fees (denominated in gas) are charged under three distinct circumstances. Sometimes, some policies may be omitted.

* The first and most common is the `constantGas`. It's a fee intrinsic to the computation of the operation.
* Second, gas may be deducted to form the payment for a subordinate message call or contract creation; this forms part of the payment for `CREATE`, `CALL` and `CALLCODE`.
* Finally, gas may be charged due to an increase in memory usage.

Over an account's execution, the total fee payable for memory-usage payable is proportional to the smallest multiple of 32 bytes that are required to include all memory indices (whether for read or write) in the range. This fee is paid on a just-in-time basis; consequently, referencing an area of memory at least 32 bytes greater than any previously indexed memory will result in an additional memory usage fee. Due to this fee, it is highly unlikely that addresses will ever exceed the 32-bit bounds. That said, implementations must be able to manage this eventuality.

Storage fees have a slightly nuanced behavior. To incentivize minimization of the use of storage (which corresponds directly to a larger state database on all nodes), the execution fee for an operation that clears an entry from storage is not only waived but also elicits a qualified refund; in fact, this refund is effectively paid in advance because the initial usage of a storage location costs substantially more than normal usage.

#### Fee Schedule <a href="#fee-schedule" id="fee-schedule"></a>

The fee schedule `G` is a tuple of 37 scalar values corresponding to the relative costs, in gas, of a number of abstract operations that a transaction may incur. Also, there's gas items to calculate the gas of the precompiled contracts called by `CALL_*` opcodes. For other tables such as `intrinsic gas cost` or `key validation gas cost`, please refer to [this document](/content/klaytn/design/transaction-fees)

**Scalar values representing `constantGas` of an opcode**

| Name                                           | Value |                                                        Name in code | Opcodes                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| ---------------------------------------------- | ----: | ------------------------------------------------------------------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `G_base`                                       |     2 |                                                        GasQuickStep | <p><code>ADDRESS</code>, <code>ORIGIN</code>, <code>CALLER</code>, <code>CALLVALUE</code>, <code>CALLDATASIZE</code>,<br><code>CODESIZE</code>, <code>GASPRICE</code>, <code>COINBASE</code>, <code>TIMESTAMP</code>, <code>NUMBER</code>,<br><code>PREVRANDAO(originally it was difficulty)</code>, <code>GASLIMIT</code>,<br><code>RETURNDATASIZE</code>, <code>POP</code>, <code>PC</code>, <code>MSIZE</code>, <code>GAS</code>,<br><code>CHAINID(added at istanbul hardfork)</code>,<br><code>BASEFEE(added at london Hardfork)</code>,<br><code>PUSH0(added at shanghai Hardfork)</code></p> |
| `G_verylow`                                    |     3 |                                                      GasFastestStep | <p><code>ADD</code>, <code>SUB</code>, <code>LT</code>, <code>GT</code>, <code>SLT</code>, <code>SGT</code>, <code>EQ</code>, <code>ISZERO</code>, <code>AND</code>,<br><code>OR</code>, <code>XOR</code>, <code>NOT</code>, <code>BYTE</code>, <code>CALLDATALOAD</code>,<br><code>MLOAD</code>, <code>MSTORE</code>, <code>MSTORE8</code>, <code>PUSH</code>, <code>DUP</code>, <code>SWAP</code></p>                                                                                                                                                                                            |
| `G_low`                                        |     5 |                                                         GasFastStep | <p><code>MUL</code>, <code>DIV</code>, <code>SDIV</code>, <code>MOD</code>, <code>SMOD</code>, <code>SIGNEXTEND</code>,<br><code>SELFBALANCE(added at istanbul hardfork)</code></p>                                                                                                                                                                                                                                                                                                                                                                                                                |
| `G_mid`                                        |     8 |                                                          GasMidStep | `ADDMOD`, `MULMOD`, `JUMP`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `G_high`                                       |    10 |                                                         GasSlowStep | `JUMPI`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `G_selfdestruct`                               |  5000 |                                                     SelfdestructGas | `SELFDESTRUCT`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| <p><code>G\_warmStorageReadCost</code><br></p> |   100 | <p>WarmStorageReadCostEIP2929<br>(newly added at Kore hardfork)</p> | <p><code>EXTCODECOPY</code>, <code>EXTCODESIZE</code>, <code>EXTCODEHASH</code>, <code>BALANCE</code>,<br><code>CALL</code>, <code>CALLCODE</code>, <code>STATICCALL</code>, <code>DELEGATECALL</code></p>                                                                                                                                                                                                                                                                                                                                                                                         |
| `G_blockhash`                                  |    20 |                                                          GasExtStep | `BLOCKHASH`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `G_jumpdest`                                   |     1 |                                                         JumpdestGas | `JUMPDEST`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `G_sha3`                                       |    30 |                                                             Sha3Gas | `SHA3`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `G_create`                                     | 32000 |                                                           CreateGas | `CREATE`, `CREATE2`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |

**Scalar values used to calculate the gas based on memory and log usage**

| Name         | Value | Name in Code | Description                                                                   |
| ------------ | ----: | -----------: | ----------------------------------------------------------------------------- |
| `G_memory`   |     3 |    MemoryGas | Amount of gas paid for every additional word when expanding memory            |
| `G_copy`     |     3 |      CopyGas | Partial payment for `COPY` operations, multiplied by words copied, rounded up |
| `G_log`      |   375 |       LogGas | Partial payment for a `LOG` operation                                         |
| `G_logdata`  |     8 |   LogDataGas | Amount of gas paid for each byte in a `LOG` operation's data                  |
| `G_logtopic` |   375 |  LogTopicGas | Amount of gas paid for each topic of a `LOG` operation                        |

**Scalar values used to calculate the gas of the particular opcode**

| Name              | Value | Name in Code                      | Description                                                                                                                    |
| ----------------- | ----: | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `G_sset`          | 20000 | SstoreSetGas                      | Amount of gas paid when the storage value when set storage                                                                     |
| `G_sreset`        |  5000 | SstoreResetGas                    | Amount of gas paid when the storage value remains unchanged at zero or is set to zero                                          |
| `G_coldSloadCost` |  2100 | ColdSloadCostEIP2929              | Amount of gas paid when the storage value is not in accessList                                                                 |
| `R_sclear`        | 15000 | SstoreClearsScheduleRefundEIP3529 | `G_sreset` - `G_coldSloadCost` + `TxAccessListStorageKeyGas (1900)`                                                            |
| `G_exp`           |    10 | ExpGas                            | Partial payment                                                                                                                |
| `G_expbyte`       |    50 | ExpByte                           | Partial payment when multiplied by `ceil(log_256(exponent))`                                                                   |
| `G_selfdestruct`  |  5000 | SelfdestructGas                   | Amount of gas paid for a `SELFDESTRUCT` operation                                                                              |
| `G_callvalue`     |  9000 | CallValueTransferGas              | Amount of gas paid for a nonzero value transfer                                                                                |
| `G_callstipend`   |  2300 | CallStipend                       | Free gas given at beginning of call for a nonzero value transfer                                                               |
| `G_newaccount`    | 25000 | CallNewAccountGas                 | Amount of gas paid when creating an account. It is also be defined as `CreateBySelfdestructGas` with `SELFDESTRUCT` operation. |
| `G_codedeposit`   |   200 | CreateDataGas                     | Amount of gas paid per byte for a creating a contract that succeeds in placing code into state                                 |
| `G_sha3word`      |     6 | Sha3WordGas                       | Amount of gas paid for each word (rounded up) for an `SHA3` input data                                                         |

**Items to calculate the precompiled contracts gas**

Precompiled contracts are special kind of contracts which usually perform complex cryptographic computations and are initiated by other contracts.

For example, gas cost can be calculated simply like below, but some gas cost calculation functions are very complex. So I would not explain the exact gas cost calculation function here.

```
# ecrecover, sha256hash, ripemd160hash, dataCopy
Gas = XXXBaseGas + (number of words * XXXPerWordGas)

# validateSender
Gas = number of signatures * ValidateSenderGas
```

| Address | Precompiled contracts | Item                                         | Value        |
| ------- | --------------------- | -------------------------------------------- | ------------ |
| 0x01    | ecrecover             | EcrecoverGas                                 | 3000         |
| 0x02    | sha256hash            | Sha256BaseGas, Sha256PerWordGas              | 60, 12       |
| 0x03    | ripemd160hash         | Ripemd160BaseGas, Ripemd160PerWordGas        | 600, 120     |
| 0x04    | dataCopy              | IdentityBaseGas, IdentityPerWordGas          | 15, 3        |
| 0x05    | bigModExp             | ModExpQuadCoeffDiv                           | 20           |
| 0x06    | bn256Add              | Bn256AddGas                                  | 150          |
| 0x07    | bn256ScalarMul        | Bn256ScalarMulGas                            | 6000         |
| 0x08    | bn256Pairing          | Bn256PairingBaseGas, Bn256PairingPerPointGas | 45000, 34000 |
| 0x09    | blake2f               | -                                            | -            |
| 0xFD    | vmLog                 | VMLogBaseGas, VMLogPerByteGas                | 100, 20      |
| 0xFE    | feePayer              | FeePayerGas                                  | 300          |
| 0xFF    | validateSender        | ValidateSenderGas                            | 5000         |

#### Gas calculation during contract execution <a href="#gas-calculation-during-contract-execution" id="gas-calculation-during-contract-execution"></a>

The gas cost of one transaction is calculated through the methods described below. First, gas is added according to the transaction type and input. Then, if the contract is executed, opcodes are executed one by one until the execution ends or `STOP` operation appears. In the process, the cost is charged according to the `constantGas` defined for each opcode and the additionally defined gas calculation method.

Here, I will briefly explain the gas calculation logic during contract execution using the fee schedule variables defined above. As this explanation assumes a general situation, the unusual situations such as revert appears is not considered.

* add `constantGas` defined in each opcode to gas
  * e.g. if an opcode is `MUL`, add `G_low` to gas
  * e.g. if an opcode is `CREATE2`, add `G_create` to gas
* add the gas which is calculated through additionally defined gas calculation method
  * For `LOG'N'`, where N is \[0,1,2,3,4], add `G_log + memoryGasCost * g_logdata + N x G_logtopic` to gas
  * For `EXP`, add `G_exp + byteSize(stack.back(1)) x G_expbyte` to gas
  * For `CALLDATACOPY` or `CODECOPY` or `RETURNDATACOPY`, add `wordSize(stack.back(2)) x G_copy` to gas
  * For `EXTCODECOPY`,
    * add `wordSize(stack.back(3)) x G_copy` to gas
    * \[***eip2929***] If an address is not in AccessList, add it to accessList and add `G_coldSloadCost - G_warmStorageReadCost` to gas
  * For `EXTCODESIZE` or `EXTCODEHASH` or `BALANCE`,
    * \[***eip2929***] If an address is not in AccessList, add it to accessList and add `G_coldSloadCost - G_warmStorageReadCost` to gas
  * For `SHA3`, add `G_sha3 + wordSize(stack.back(1)) x G_sha3word` to gas
  * For `RETURN`, `REVERT`, `MLoad`, `MStore8`, `MStore`, add `memoryGasCost` to gas
  * For `CREATE`, add `memoryGasCost + size(contract.code) x G_codedeposit` to gas
  * For `CREATE2`, add `memoryGasCost + size(data) x G_sha3word + size(contract.code) x G_codedeposit` to gas
  * For `SSTORE`,
    * \[***eip2929***] If a slot(contractAddr, slot) is not in AccessList, add it to accessList and add `G_coldSloadCost` to gas
    * If it just reads the slot (no-op), add `G_warmStorageReadCost` to gas
    * If it creates a new slot, add `G_sset` to gas
    * If it deletes the slot, add `G_sreset-G_coldSloadCost` to gas and add `R_sclear` to refund
    * If it recreates the slot once exists before, add `G_warmStorageReadCost` to gas and subtract `R_sclear` from refund
    * If it deletes the slot once exists before, add `R_sclear` to refund
    * If it resets to the original inexistent slot, add `G_warmStorageReadCost` to gas and add `G_sset - G_warmStorageReadCost` to refund
    * IF it resets to the original existing slot, add `G_warmStorageReadCost` to gas and add `G_sreset - G_coldSloadCost - G_warmStorageReadCost` to refund
  * For `SLOAD`,
    * \[***eip2929***] If a slot(contractAddr, slot) is not in AccessList, add it to accessList and add `G_coldSloadCost` to gas
    * \[***eip2929***] If a slot(contractAddr, slot) is in AccessList, add `G_warmStorageReadCost` to gas
  * For `CALL`, `CALLCODE`, `DELEGATECALL`, `STATICCALL`,
    * \[***eip2929***] If an address is not in AccessList, add it to accessList and add `G_coldSloadCost` to gas
    * if it is `CALL` and `CALLCODE` and if it transfers value, add `G_callvalue` to gas
    * if it is `CALL` and if it transfers value and if it is a new account, add `G_newaccount` to gas
    * if the callee contract is precompiled contracts, calculate precompiled contract gas cost and add it to gas
    * add `memoryGasCost + availableGas - availableGas/64, where availableGas = contract.Gas - gas` to gas
  * For `SELFDESTRUCT`,
    * \[***eip2929***] If an address is not in AccessList, add it to accessList and add `G_coldSloadCost` to gas
    * if it transfers value and if is a new account, add `G_newaccount` to gas

### Execution Environment <a href="#execution-environment" id="execution-environment"></a>

The execution environment consists of the system state `S_system`, the remaining gas for computation `G_rem`, and the information `I` that the execution agent provides. `I` is a tuple defined as shown below:

`I := (B_header, T_code, T_depth, T_value, T_data, A_tx_sender, A_code_executor, A_code_owner, G_price, P_modify_state)`

The execution model defines the function `F_apply`, which can compute the resultant state `S_system'`, the remaining gas `G_rem'`, the accrued substate `A` and the resultant output `O_result` when given these definitions. For the present context, we will define it as follows:

`(S_system', G_rem', A, O_result) = F_apply(S_system, G_rem, I)`

where we must remember that `A`, the accrued substate, is defined as the tuple of the suicides set `Set_suicide`, the log series `L`, the touched accounts `Set_touched_accounts` and the refunds `G_refund`:

`A := (Set_suicide, L, Set_touched_accounts, G_refund)`

### Execution Overview <a href="#execution-overview" id="execution-overview"></a>

In most practical implementations, `F_apply` will be modeled as an iterative progression of the pair comprising the full system state `S_system` and the machine state `S_machine`. Formally, we define it recursively with a function `X` that uses an iterator function `O` (which defines the result of a single cycle of the state machine) together with functions `Z`, which determines if the present state is an exceptional halted machine state, and `H`, which specifies the output data of an instruction if and only if the present state is a normal halted machine state.

The empty sequence, denoted as `()`, is not equal to the empty set, denoted as `Set_empty`; this is important when interpreting the output of `H`, which evaluates to `Set_empty` when execution is to continue but to a series (potentially empty) when execution should halt.

`F_apply(S_machine, G_rem, I, T) := (S_system', S_machine,g', A, o)`

* `(S_system', S_machine,g', A, ..., o) := X((S_system, S_machine, A^0, I))`
* `S_machine,g := G_rem`
* `S_machine,pc := 0`
* `S_machine,memory := (0, 0, ...)`
* `S_machine,i := 0`
* `S_machine,stack := ()`
* `S_machine,o := ()`
* `X((S_system, S_machine, A, I)) :=`
  * `(Set_empty, S_machine, A^0, I, Set_empty)` if `Z(S_system, S_machine, I)`
  * `(Set_empty, S_machine', A^0, I, o)` if `w = REVERT`
  * `O(S_system, S_machine, A, I) · o` if `o != Set_empty`
  * `X(O(S_system, S_machine, A, I))` otherwise

where

* `o := H(S_machine, I)`
* `(a, b, c, d) · e := (a, b, c, d, e)`
* `S_machine' := S_machine` except

  `S_machine,g' := S_machine,g - C(S_system, S_machine, I)`

  * This means that when we evaluate `F_apply`, we

    extract the remaining gas `S_machine,g'` from the

    resultant machine state `S_machine'`.

`X` is thus cycled (recursively here, but implementations are generally expected to use a simple iterative loop) until either `Z` becomes true, indicating that the present state is exceptional and that the machine must be halted and any changes are discarded, or until `H` becomes a series (rather than the empty set), indicating that the machine has reached a controlled halt.

#### Machine State <a href="#machine-state" id="machine-state"></a>

The machine state `S_machine` is defined as a tuple `(g, pc, memory, i, stack)`, which represent the available gas, the program counter `pc` (64-bit unsigned integer), the memory contents, the active number of words in memory (counting continuously from position 0), and the stack contents. The memory contents `S_machine,memory` are a series of zeroes of size 2^256.

For ease of reading, the instruction mnemonics written in small-caps (*e.g.*, `ADD`) should be interpreted as their numeric equivalents; the full table of instructions and their specifics is given in the [Instruction Set](https://github.com/klaytn/klaytn-docs-ko/blob/main/docs/klaytn/design/computation/klaytn-virtual-machine/klaytn-virtual-machine/README.md#instruction-set) section.

To define `Z`, `H` and `O`, we define `w` as the current operation to be executed:

* `w := T_code[S_machine,pc]` if `S_machine,pc < len(T_code)`
* `w :=STOP` otherwise

### Instruction Set <a href="#instruction-set" id="instruction-set"></a>

NOTE: This section will be filled in the future.

## How KLVM Differs From EVM <a href="#how-klvm-differs-from-evm" id="how-klvm-differs-from-evm"></a>

As mentioned earlier, the current KLVM is based on EVM; thus, its specification currently is very similar to that of EVM. Some differences between KLVM and EVM are listed below.

* KLVM uses Klaytn's gas units, such as peb, ston, or KLAY.
* KLVM does not accept a gas price from the user; instead, it uses a platform-defined value as the gas price.

The Klaytn team will try to maintain compatibility between KLVM and EVM, but as Klaytn becomes increasingly implemented and evolves, the KLVM specification will be updated, and there will probably be more differences compared to EVM.

NOTE: This section will be updated in the future.


# 클레이튼 가상머신 (구 버전 문서)

{% hint style="success" %}
NOTE: This document contains the KLVM used before the activation of the protocol upgrade. If you want the latest document, please refer to [latest document](/content/klaytn/design/computation/klaytn-virtual-machine).
{% endhint %}

## Overview <a href="#overview" id="overview"></a>

The current version of the Klaytn Virtual Machine (KLVM) is derived from the Ethereum Virtual Machine (EVM). The content of this chapter is based primarily on the [Ethereum Yellow Paper](https://github.com/ethereum/yellowpaper). KLVM is continuously being improved by the Klaytn team, thus this document could be updated frequently. Please do not regard this document as the final version of the KLVM specification. As described in the Klaytn position paper, the Klaytn team also plans to adopt other virtual machines or execution environments in order to strengthen the capability and performance of the Klaytn platform. This chapter presents a specification of KLVM and the differences between KLVM and EVM.

KLVM is a virtual state machine that formally specifies Klaytn's execution model. The execution model specifies how the system state is altered given a series of bytecode instructions and a small tuple of environmental data. KLVM is a quasi-Turing-complete machine; the *quasi* qualification stems from the fact that the computation is intrinsically bounded through a parameter, *gas*, which limits the total amount of computation performed.

KLVM executes Klaytn virtual machine code (or Klaytn bytecode) which consists of a sequence of KLVM instructions. The KLVM code is the programming language used for accounts on the Klaytn blockchain that contain code. The KLVM code associated with an account is executed every time a message is sent to that account; this code has the ability to read/write from/to storage and send messages.

## KLVM 사양 <a href="#klvm-specification" id="klvm-specification"></a>

### 표기 규칙 <a href="#conventions" id="conventions"></a>

We use the following notations and conventions in this document.

* `A := B`
  * `: =` `A를 <code> B로` 정의하는 데 사용됩니다.
* "스마트 컨트랙트"와 "컨트랙트"라는 용어를 번갈아 사용합니다.
* We use the terms "opcode" as the "operation code/operation"

### 기호 <a href="#symbols" id="symbols"></a>

The following tables summarize the symbols used in the KLVM specification.

#### 블록체인 관련 기호 <a href="#blockchain-related-symbols" id="blockchain-related-symbols"></a>

| 기호         | Description  |
| ---------- | ------------ |
| `BC`       | 블록체인         |
| `B`        | Block        |
| `B_header` | 현재 블록의 블록 헤더 |

#### 상태 관련 기호(State-Related Symbols) <a href="#state-related-symbols" id="state-related-symbols"></a>

| Symbol           | Description |
| ---------------- | ----------- |
| `S`              | 상태(State)   |
| `S_system`       | 시스템 상태      |
| `S_machine`      | 머신 상태       |
| `P_modify_state` | 상태 수정 권한    |

#### 트랜잭션 관련 기호(Transaction-related symbols) <a href="#transaction-related-symbols" id="transaction-related-symbols"></a>

| Symbol    | Description                                                                 |
| --------- | --------------------------------------------------------------------------- |
| `T`       | Transaction                                                                 |
| `T_code`  | 실행할 머신 코드를 포함하는 바이트 배열(byte array)                                          |
| `T_data`  | 입력 데이터를 포함하는 바이트 배열. 실행 에이전트(execution agent)가 트랜잭션인 경우, 이것은 트랜잭션 데이터가 됩니다. |
| `T_value` | Pep 단위로 표기된 값이 실행 과정 중에 계정을 전달됩니다. 만약 실행 에이전트가 트랙잭션이라면 이 값은 트랜잭션 값이 됩니다.    |
| `T_depth` | 현재 메시지 호출 또는 컨트랙트 작성 스택의 깊이 (*즉,* 현재 `호출` 또는 `실행` 횟수)                       |

#### 가스 관련 기호(Gas-Related Symbols) <a href="#gas-related-symbols" id="gas-related-symbols"></a>

| Symbol    | Description          |
| --------- | -------------------- |
| `G`       | 가스                   |
| `G_rem`   | 연산에 사용하기 위한 남은 잔여 가스 |
| `G_price` | 실행 시작한 트랜잭션의 가스 가격   |

#### 주소 관련 기호(Adress-Related Symbols) <a href="#address-related-symbols" id="address-related-symbols"></a>

| Symbol            | Description                                                              |
| ----------------- | ------------------------------------------------------------------------ |
| `A`               | Address                                                                  |
| `A_code_owner`    | 실행 코드를 소유한 계정의 주소                                                        |
| `A_tx_sender`     | 현재 실행을 시작한 트랜잭션의 발신자 주소                                                  |
| `A_code_executor` | 코드를 실행한 계정의 주소. 실행 에이전트가 트랜잭션이라면, 이는 트랜잭션 발신자(transaction sender) 가 됩니다. |

#### 함수 <a href="#functions" id="functions"></a>

|   Symbol  | Description                                |
| :-------: | ------------------------------------------ |
| `F_apply` | 주어진 상태에 입력된 트랜잭션을 적용하고 결과 상태 및 출력을 반환하는 함수 |

### 기본 사항 <a href="#basics" id="basics"></a>

KLVM is a simple stack-based architecture. The word size of the machine (and thus the size of stack items) is 256-bit. This was chosen to facilitate the Keccak-256 hash scheme and the elliptic-curve computations. The memory model is a simple word-addressed byte array. The stack has a maximum size of 1024. The machine also has an independent storage model; this is similar in concept to the memory but rather than a byte array, it is a word-addressable word array. Unlike memory, which is volatile, storage is nonvolatile and is maintained as part of the system state. All locations in both storage and memory are initially well-defined as zero.

The machine does not follow the standard von Neumann architecture. Rather than storing program code in generally accessible memory or storage, code is stored separately in virtual read-only memory and can be interacted with only through specialized instructions.

The machine can execute exception code for several reasons, including stack underflows and invalid instructions. Similar to an out-of-gas exception, these exceptions do not leave state changes intact. Rather, the virtual machine halts immediately and reports the issue to the execution agent (either the transaction processor or, recursively, the spawning execution environment), which will be addressed separately.

### 트랜잭션 수수료 개요 <a href="#fees-overview" id="fees-overview"></a>

Fees (denominated in gas) are charged under three distinct circumstances.

* The first and most common is the `constantGas`. It's a fee intrinsic to the computation of the operation.
* Second, gas may be deducted to form the payment for a subordinate message call or contract creation; this forms part of the payment for `CREATE`, `CALL` and `CALLCODE`.
* Finally, gas may be charged due to an increase in memory usage.

Over an account's execution, the total fee payable for memory-usage payable is proportional to the smallest multiple of 32 bytes that are required to include all memory indices (whether for read or write) in the range. This fee is paid on a just-in-time basis; consequently, referencing an area of memory at least 32 bytes greater than any previously indexed memory will result in an additional memory usage fee. Due to this fee, it is highly unlikely that addresses will ever exceed the 32-bit bounds. That said, implementations must be able to manage this eventuality.

Storage fees have a slightly nuanced behavior. To incentivize minimization of the use of storage (which corresponds directly to a larger state database on all nodes), the execution fee for an operation that clears an entry from storage is not only waived but also elicits a qualified refund; in fact, this refund is effectively paid in advance because the initial usage of a storage location costs substantially more than normal usage.

#### 비용표 <a href="#fee-schedule" id="fee-schedule"></a>

The fee schedule `G` is a tuple of 37 scalar values corresponding to the relative costs, in gas, of a number of abstract operations that a transaction may incur. Also, there's gas items to calculate the gas of the precompiled contracts called by `CALL_*` opcodes. For other tables such as `intrinsic gas cost` or `key validation gas cost`, please refer to [this document](/content/klaytn/design/transaction-fees)

**Scalar values representing `constantGas` of an opcode**

| Name            |     값 |   Name in code | Opcodes                                                                                                                                                                                                                                                                                                                                                                                                 |
| --------------- | ----: | -------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `G_base`        |     2 |   GasQuickStep | <p><code>ADDRESS</code>, <code>ORIGIN</code>, <code>CALLER</code>, <code>CALLVALUE</code>, <code>CALLDATASIZE</code>,<br><code>CODESIZE</code>, <code>GASPRICE</code>, <code>COINBASE</code>, <code>TIMESTAMP</code>, <code>NUMBER</code>,<br><code>DIFFICULTY</code>, <code>GASLIMIT</code>, <code>RETURNDATASIZE</code>, <code>POP</code>, <code>PC</code>, <code>MSIZE</code>, <code>GAS</code></p>  |
| `G_verylow`     |     3 | GasFastestStep | <p><code>ADD</code>, <code>SUB</code>, <code>LT</code>, <code>GT</code>, <code>SLT</code>, <code>SGT</code>, <code>EQ</code>, <code>ISZERO</code>, <code>AND</code>,<br><code>OR</code>, <code>XOR</code>, <code>NOT</code>, <code>BYTE</code>, <code>CALLDATALOAD</code>,<br><code>MLOAD</code>, <code>MSTORE</code>, <code>MSTORE8</code>, <code>PUSH</code>, <code>DUP</code>, <code>SWAP</code></p> |
| `G_low`         |     5 |    GasFastStep | `MUL`, `DIV`, `SDIV`, `MOD`, `SMOD`, `SIGNEXTEND`                                                                                                                                                                                                                                                                                                                                                       |
| `G_mid`         |     8 |     GasMidStep | `ADDMOD`, `MULMOD`, `JUMP`                                                                                                                                                                                                                                                                                                                                                                              |
| `G_high`        |    10 |    GasSlowStep | `JUMPI`                                                                                                                                                                                                                                                                                                                                                                                                 |
| `G_blockhash`   |    20 |     GasExtStep | `BLOCKHASH`                                                                                                                                                                                                                                                                                                                                                                                             |
| `G_balance`     |   400 |     BalanceGas | `BALANCE`                                                                                                                                                                                                                                                                                                                                                                                               |
| `G_sload`       |   200 |       SloadGas | `SLOAD`                                                                                                                                                                                                                                                                                                                                                                                                 |
| `G_jumpdest`    |     1 |    JumpdestGas | `JUMPDEST`                                                                                                                                                                                                                                                                                                                                                                                              |
| `G_sha3`        |    30 |        Sha3Gas | `SHA3`                                                                                                                                                                                                                                                                                                                                                                                                  |
| `G_call`        |   700 |        CallGas | `CALL`, `CALLCODE`, `STATICCALL`, `DELEGATECALL`                                                                                                                                                                                                                                                                                                                                                        |
| `G_create`      | 32000 |      CreateGas | `CREATE`, `CREATE2`                                                                                                                                                                                                                                                                                                                                                                                     |
| `G_extcodesize` |   700 | ExtcodeSizeGas | `EXTCODESIZE`                                                                                                                                                                                                                                                                                                                                                                                           |
| `G_extcodehash` |   400 | ExtcodeHashGas | `EXTCODEHASH`                                                                                                                                                                                                                                                                                                                                                                                           |

**Scalar values used to calculate the gas based on memory and log usage**

| Name         | Value | Name in Code | Description                                                                   |
| ------------ | ----: | -----------: | ----------------------------------------------------------------------------- |
| `G_memory`   |     3 |    MemoryGas | Amount of gas paid for every additional word when expanding memory            |
| `G_copy`     |     3 |      CopyGas | Partial payment for `COPY` operations, multiplied by words copied, rounded up |
| `G_log`      |   375 |       LogGas | Partial payment for a `LOG` operation                                         |
| `G_logdata`  |     8 |   LogDataGas | Amount of gas paid for each byte in a `LOG` operation's data                  |
| `G_logtopic` |   375 |  LogTopicGas | Amount of gas paid for each topic of a `LOG` operation                        |

**Scalar values used to calculate the gas of the particular opcode**

| Name             | Value | Name in Code                   | Description                                                                                                                    |
| ---------------- | ----: | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
| `G_sset`         | 20000 | SstoreSetGas                   | Amount of gas paid when the storage value when set storage                                                                     |
| `G_sreset`       |  5000 | SstoreResetGas, SstoreClearGas | Amount of gas paid when the storage value remains unchanged at zero or is set to zero                                          |
| `R_sclear`       | 15000 | SstoreRefundGas                | Refund Gas given (added to the refund counter) when the storage value is set to zero from nonzero                              |
| `G_exp`          |    10 | ExpGas                         | Partial payment                                                                                                                |
| `G_expbyte`      |    50 | ExpByte                        | Partial payment when multiplied by `ceil(log_256(exponent))`                                                                   |
| `G_selfdestruct` |  5000 | SelfdestructGas                | Amount of gas paid for a `SELFDESTRUCT` operation                                                                              |
| `R_selfdestruct` | 24000 | SelfdestructRefundGas          | Refund Gas given (added to the refund counter) for self-destructing an account                                                 |
| `G_callvalue`    |  9000 | CallValueTransferGas           | Amount of gas paid for a nonzero value transfer                                                                                |
| `G_callstipend`  |  2300 | CallStipend                    | Free gas given at beginning of call for a nonzero value transfer                                                               |
| `G_newaccount`   | 25000 | CallNewAccountGas              | Amount of gas paid when creating an account. It is also be defined as `CreateBySelfdestructGas` with `SELFDESTRUCT` operation. |
| `G_codedeposit`  |   200 | CreateDataGas                  | Amount of gas paid per byte for a creating a contract that succeeds in placing code into state                                 |
| `G_sha3word`     |     6 | Sha3WordGas                    | Amount of gas paid for each word (rounded up) for an `SHA3` input data                                                         |

**Items to calculate the precompiled contracts gas**

Precompiled contracts are special kind of contracts which usually perform complex cryptographic computations and are initiated by other contracts.

For example, gas cost can be calculated simply like below, but some gas cost calculation functions are very complex. So I would not explain the exact gas cost calculation function here.

```
# ecrecover, sha256hash, ripemd160hash, dataCopy
Gas = XXXBaseGas + (number of words * XXXPerWordGas)

# validateSender
Gas = number of signatures * ValidateSenderGas
```

| Address | Precompiled contracts | Item                                         | Value        |
| ------- | --------------------- | -------------------------------------------- | ------------ |
| 0x01    | ecrecover             | EcrecoverGas                                 | 3000         |
| 0x02    | sha256hash            | Sha256BaseGas, Sha256PerWordGas              | 60, 12       |
| 0x03    | ripemd160hash         | Ripemd160BaseGas, Ripemd160PerWordGas        | 600, 120     |
| 0x04    | dataCopy              | IdentityBaseGas, IdentityPerWordGas          | 15, 3        |
| 0x05    | bigModExp             | ModExpQuadCoeffDiv                           | 20           |
| 0x06    | bn256Add              | Bn256AddGas                                  | 150          |
| 0x07    | bn256ScalarMul        | Bn256ScalarMulGas                            | 6000         |
| 0x08    | bn256Pairing          | Bn256PairingBaseGas, Bn256PairingPerPointGas | 45000, 34000 |
| 0x09    | vmLog                 | VMLogBaseGas, VMLogPerByteGas                | 100, 20      |
| 0x10    | feePayer              | FeePayerGas                                  | 300          |
| 0x11    | validateSender        | ValidateSenderGas                            | 5000         |

#### Gas calculation during contract execution <a href="#gas-calculation-during-contract-execution" id="gas-calculation-during-contract-execution"></a>

The gas cost of one transaction is calculated through the methods described below. First, gas is added according to the transaction type and input. Then, if the contract is executed, opcodes are executed one by one until the execution ends or `STOP` operation appears. In the process, the cost is charged according to the `constantGas` defined for each opcode and the additionally defined gas calculation method.

Below is a brief explanation of the gas calculation logic during contract execution using the fee schedule variables defined above. As it assumes a general situation, unusual situations such as revert appears is not considered.

* add `constantGas` defined in each opcode to gas
  * e.g. if an opcode is `MUL`, add `G_low` to gas
  * e.g. if an opcode is `CREATE2`, add `G_create` to gas
* add the gas which is calculated through additionally defined gas calculation method
  * For `LOG'N'`, where N is \[0,1,2,3,4], add `G_log + memoryGasCost * g_logdata + N x G_logtopic` to gas
  * For `EXP`, add `G_exp + byteSize(stack.back(1)) x G_expbyte` to gas
  * For `CALLDATACOPY` or `CODECOPY` or `RETURNDATACOPY`, add `wordSize(stack.back(2)) x G_copy` to gas
  * For `EXTCODECOPY`, add `wordSize(stack.back(3)) x G_copy` to gas
  * For `SHA3`, add `G_sha3 + wordSize(stack.back(1)) x G_sha3word` to gas
  * For `RETURN`, `REVERT`, `MLoad`, `MStore8`, `MStore`, add `memoryGasCost` to gas
  * For `CREATE`, add `memoryGasCost + size(contract.code) x G_codedeposit`
  * For `CREATE2`, add `memoryGasCost + size(data) x G_sha3word + size(contract.code) x G_codedeposit` to gas
  * For `SSTORE`,
    * From a zero-value address to a non-zero value (NEW VALUE), add `G_sset` to gas
    * From a non-zero value address to a zero-value address (DELETE), add `G_sreset` to gas and add `R_sclear` to refund
    * From a non-zero to a non-zero (CHANGE), add `G_sreset` to gas
  * For `CALL`, `CALLCODE`, `DELEGATECALL`, `STATICCALL`,
    * if it is `CALL` and `CALLCODE` and if it transfers value, add `G_callvalue` to gas
    * if it is `CALL` and if it transfers value and if it is a new account, add `G_newaccount` to gas
    * if the callee contract is precompiled contracts, calculate precompiled contract gas cost and add it to gas
    * add `memoryGasCost + availableGas - availableGas/64, where availableGas = contract.Gas - gas` to gas
  * For `SELFDESTRUCT`,
    * if it transfers value and if is a new account, add `G_newaccount` to gas
    * if the contract has not suicided yet, add `R_selfdestruct` to refund

### 실행 환경 <a href="#execution-environment" id="execution-environment"></a>

실행 환경은 시스템 상태 `S_system`, 연산을 위해 남은 가스 `G_rem`, 실행 에이전트가 제공하는 정보 `I`으로 이루어져 있습니다. `I`는 다음과 같이 정의된 튜플입니다.

`I := (B_header, T_code, T_depth, T_value, T_data, A_tx_sender, A_code_executor, A_code_owner, G_price, P_modify_state)`

실행 모델은 `F_apply` 함수를 정의하는데, 이로 결과로 나온 상태 `S_system'`, 잔류 가스 `G_rem '` , 발생한 하위 상태 `A` 및 결과적인 출력 `O_result` 를 계산할 수 있습니다. 현재는 다음과 같이 정의합니다.

`(S_system', G_rem', A, O_result) = F_apply(S_system, G_rem, I)`

여기서 우리는 발생된 하위 상태인 `A`는 suicides 집합인 `Set_suicide`, 로그 시리즈 `L`, 접근한 계정의 집합 `Set_touched_accounts` , 그리고 환불 `G_refund`의 튜플로 정의된다는 것을 기억해야 합니다.

`A := (Set_suicide, L, Set_touched_accounts, G_refund)`

### 실행 개요 <a href="#execution-overview" id="execution-overview"></a>

대부분의 실제 구현에서 `F_apply`는 전체 시스템 상태 `S_system`과 머신 상태 `S_machine` 쌍의 반복적인 진행으로 모델링됩니다. 형태적으로, 우리는 상태 머신에서 하나의 사이클의 결과값을 정의하는 이터레이터 함수 `O`와 현재 상태가 예외적으로 중단된 머신 상태인지 확인하는 함수 `Z`, 그리고 현재 상태가 정상적으로 중단된 머신 상태일 경우에만 명령어의 출력 데이터를 지정하는 `H`를 사용하는 함수 `X`를 이용하여 재귀적으로 정의합니다.

빈 시퀀스 `()`는 빈 Set을 가리키는 `Set_empty`와는 다릅니다. 이는 `H`의 결과를 해석할 때 중요한데, 실행을 계속해도 된다면 결과가 `Set_empty`이고 실행이 중지되어야 한다면 결과가 (아마도 비어 있을)시퀀스이기 때문입니다.

`F_apply(S_machine, G_rem, I, T) := (S_system', S_machine,g', A, o)`

* `(S_system', S_machine,g', A, ..., o) := X((S_system, S_machine, A^0, I))`
* `S_machine,g := G_rem`
* `S_machine,pc := 0`
* `S_machine,memory := (0, 0, ...)`
* `S_machine,i := 0`
* `S_machine,stack := ()`
* `S_machine,o := ()`
* `X((S_system, S_machine, A, I)) :=`
  * `(Set_empty, S_machine, A^0, I, Set_empty)` if `Z(S_system, S_machine, I)`
  * `(Set_empty, S_machine', A^0, I, o)` if `w = REVERT`
  * `O(S_system, S_machine, A, I) · o` if `o != Set_empty`
  * `X(O(S_system, S_machine, A, I))` otherwise

where

* `o := H(S_machine, I)`
* `(a, b, c, d) · e := (a, b, c, d, e)`
* `S_machine' := S_machine` except

  `S_machine,g' := S_machine,g - C(S_system, S_machine, I)`

  * 이는 `F_apply`를 계산할 때

    남은 가스 `S_machine,g'`를

    결과로 남은 머신 상태 `S_machine'`에서 차감한다는 의미입니다.

따라서 `Z`가 true 즉 현재 상태에 예외가 발생했으며 머신이 반드시 중지되어야 하고 따라서 모든 상태 변화는 무시되는 상황이 될 때까지, 또는 `H`가 (Set\_empty가 아닌) 시퀀스가 될 때 즉 머신이 통제 가능한 중지 상황에 이를 때까지 `X`는 재귀적으로(보통 실제 구현은 단순한 반복 루프 사용) 반복해서 정의됩니다.

#### 머신 상태 <a href="#machine-state" id="machine-state"></a>

머신 상태 `S_machine`는 튜플 `(g, pc, memory, i, stack)`로 정의됩니다. 이는 사용 가능한 가스량, 프로그램 카운터 `pc` (64-bit unsigned integer), 메모리 컨텐츠(memory contents,), 현재 메모리에 있는 단어 수(position 0부터 계속 카운팅), 스택 컨텐츠(stack contents)를 의미합니다. 메모리 컨텐츠 `S_machine,memory`는 사이즈가 2^256이며 0으로 이루어진 series입니다.

For ease of reading, the instruction mnemonics written in small-caps (*e.g.*, `ADD`) should be interpreted as their numeric equivalents; the full table of instructions and their specifics is given in the [Instruction Set](#instruction-set) section.

`Z`, `H`와 `O`를 정의하기 위해, `w`를 실행할 현재 연산으로 정의합니다.

* `w := T_code[S_machine,pc]` if `S_machine,pc < len(T_code)`
* `w :=STOP` otherwise

### 명령어 세트(Instruction Set) <a href="#instruction-set" id="instruction-set"></a>

참고: 이 장은 나중에 업데이트 될 예정입니다.

## KLVM과 EVM의 차이점 <a href="#how-klvm-differs-from-evm" id="how-klvm-differs-from-evm"></a>

앞에서 언급했듯이 현재 KLVM은 EVM을 기반으로합니다. 따라서 현재 사양은 EVM의 사양과 매우 유사합니다. KLVM과 EVM의 몇 가지 차이점은 다음과 같습니다.

* KLVM은 peb, ston 또는 KLAY와 같은 Klaytn의 가스 단위(unit)를 사용합니다.
* KLVM은 사용자로부터 가스 가격을 입력 받지 않습니다. 대신, 플랫폼이 정의한 값을 가스 가격으로 사용합니다.

Klaytn팀은 KLVM과 EVM간의 호환성을 유지하려고 노력하지만 Klaytn이 점차 구현되고 발전함에 따라 KLVM 사양이 업데이트되며, EVM과 비교하여 더 많은 차이가 생겨날 수 있습니다.

참고: 이 장은 나중에 업데이트 될 예정입니다.


# 스토리지

## State Migration <a href="#state-migration" id="state-migration"></a>

As more blocks are added to the blockchain, chain data also pile up. Chain data are necessary for node operation, so they are stored in the node storage as a data structure called trie, and ultimately in a database called LevelDB. So with more blocks, comes more chain data in the storage, along with increasing cost. Klaytn, therefore, provides a feature called State Migration that allows you to reduce the amount of required storage space.

State Migration targets state tries, which comprise most of the chain data. It deletes state trie nodes that are not required for processing new blocks. It only leaves the state trie nodes that are reachable from the state trie root of a specific block. After State Migration, you are only left with the latest data required for node synchronization, consisting of state trie nodes of the target block as well as newly added blocks.

Note that a node can't read old states from blocks previous to the target block after State Migration. In other words, you can't return the balance from an old block number using the `klay_getBalance` API.

More details on the mechanism of State Migration can be found below: [Klaytn v1.5.0 State Migration: Saving Node Storage](https://medium.com/klaytn/klaytn-v1-5-0-state-migration-saving-node-storage-1358d87e4a7a) [Klaytn State Migration: An Efficient Way to Reduce Blockchain Data](https://medium.com/klaytn/klaytn-state-migration-an-efficient-way-to-reduce-blockchain-data-6615a3b36523)

To use State Migration, please refer to [`Chaindata Migration`](https://docs.klaytn.foundation/content/operation-guide/chaindata-migration) page of Operation Guide.


# 트랜잭션 비용

{% hint style="success" %}
NOTE: The transaction fee has changed with the `Kore` hardfork. If you want the previous document, please refer to [previous document](/content/klaytn/design/transaction-fees/transaction-fees-previous).

`Kore` hardfork block numbers are as follows.

* Baobab Testnet: `#111736800`
* Cypress Mainnet: `#119750400`
  {% endhint %}

The transaction fee of one transaction is calculated as follows:

```
Transaction fee := (Gas used) x (GasPrice)
```

As an easy-to-understand analogy in this regard, suppose you're filling up gas at a gas station. The gas price is determined by the refinery every day, and today's price is $2. If you fill 15L up, then you would pay $30 = 15L x $2/1L for it, and the $30 will be paid out of your bank account. Also, the transaction will be recorded in the account book.

Transaction fee works just the same as above. The network determines the gas price for every block. Suppose the gas price for the current block is 30 ston. If a transaction submitted by `from` account was charged 21000 gas, then 630000 ston = (21000 gas \* 30 ston) would be paid out of the `from` account. Also, the transaction will be recorded in the block, and it will be applied in the state of all blockchain nodes.

Summing it up again, this calculated transaction fee is subtracted from the sender's or fee payer's account. However, the fee can be deducted from the balance only if the transaction is created by klay\_sendTransaction/eth\_sendTransaction. Because the other transactions cannot change the state since they cannot be included in the block. They are just a simulation in some way.

This is an overall explanation of the transaction fee, and from this point, we would give a detailed explanation of how gas price is determined and how the gas is calculated.

## GasPrice Overview <a href="#gas-price-overview" id="gas-price-overview"></a>

Unlike the ethereum, Klaytn used the fixed gas price, called `unitPrice` at first. However, since magma hardfork, Klaytn started to use dynamic gas price which concept is newly redesined by modifying the Ethereum's basefee, so called `Effective Gas Price`. Since there have been many changes about gas price, it can be pretty confusing on what value to set for gasPrice. So, we've made a guide on how to set the gas price below.

| Network  | Before BaseFee                                                                                                                      | After BaseFee                                                                                                                                                                                                             |
| -------- | ----------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| klaytn   | <p>tx parameter gasPrice: network-defined. must be set as the <code>unitPrice</code><br>gasPrice: use the tx parameter gasPrice</p> | <p>tx parameter gasPrice: user-defined. It means the price the most you can pay<br>(e.g. suggestGasPrice = 2\*latestBlock.baseFee )<br>gasPrice: dynamic gasPrice, <code>baseFee</code>, which is defined by network.</p> |
| Ethereum | <p>tx parameter gasPrice: user-defined. it means the price the most you can pay.<br>gasPrice: use the tx parameter gasPrice</p>     | <p>tx parameter gasPrice: user-defined. It means the price the most you can pay.<br>gasPrice: dynamic gasPrice, <code>baseFee+tip</code>, which is defined by network.</p>                                                |

### Dynamic Gas Fee Mechanism <a href="#dynamic-gas-fee-mechanism" id="dynamic-gas-fee-mechanism"></a>

Since the magma hard fork, a dynamic gas fee mechanism has replaced the existing fixed fee policy. Dynamic gas fee policy provides a stable service to users by preventing network abuse and storage overuse. The gas fee changes according to the network situation. Seven parameters affect the `base fee(gas fee)`:

1. PREVIOUS\_BASE\_FEE: Base fee of the previous block
2. GAS\_USED\_FOR\_THE\_PREVIOUS\_BLOCK: Gas used to process all transactions of the previous block
3. GAS\_TARGET: The gas amount that determines the increase or decrease of the base fee (30 million at the moment)
4. MAX\_BLOCK\_GAS\_USED\_FOR\_BASE\_FEE: Implicit block gas limit to enforce the max basefee change rate (60 million at the moment)
5. BASE\_FEE\_DELTA\_REDUCING\_DENOMINATOR: The value to set the maximum base fee change to 5% per block (20 at the moment, can be changed later by governance)
6. UPPER\_BOUND\_BASE\_FEE: The maximum value for the base fee (750 ston at the moment, can be changed later by governance)
7. LOWER\_BOUND\_BASE\_FEE: The minimum value for the base fee (25 ston at the moment, can be changed later by governance)

### Base Fee <a href="#base-fee" id="base-fee"></a>

The basic idea of this algorithm is that the `base fee` would go up if the gas used exceeds the base gas and vice versa. It is closely related to the number of transactions in the network and the gas used in the process. There is an upper and lower limit for the `base fee` to prevent the fee from increasing or decreasing indefinitely. There is also a cap for the gas and an adjustment value for the fluctuation to prevent abrupt changes in the `base fee`. The values can be changed by governance.

```
(BASE_FEE_CHANGE_RATE) = (GAS_USED_FOR_THE_PREVIOUS_BLOCK - GAS_TARGET)
(ADJUSTED_BASE_FEE_CHANGE_RATE) = (BASE_FEE_CHANGE_RATE) / (GAS_TARGET) / (BASE_FEE_DELTA_REDUCING_DENOMINATOR)
(BASE_FEE_CHANGE_RANGE) = (PREVIOUS_BASE_FEE) * (ADJUSTED_BASE_FEE_CHANGE_RATE)
(BASE_FEE) = (PREVIOUS_BASE_FEE) + (BASE_FEE_CHANGE_RANGE) 
```

The `base fee` is calculated for every block; there could be changes every second. Transactions from a single block use the same `base fee` to calculate transaction fees. Only transactions with a gas price higher than the block `base fee` can be included in the block. Half of the transaction fee for each block is burned (BURN\_RATIO = 0.5, cannot be changed by governance).

> NOTE: An important feature that sets Klaytn apart from Ethereum's EIP-1559 is that it does not have tips. Klaytn follows the First Come, First Served(FCFS) principle for its transactions.

## Gas Overview <a href="#gas-overview" id="gas-overview"></a>

Every action that changes the state of the blockchain requires gas. While processing the transactions in a block, such as sending KLAY, using KIP-7 tokens, or executing a contract, the user has to pay for the computation and storage usage. The payment amount is decided by the amount of `gas` required.

`Gas` required is computed by adding up the next two gases;

* `IntrinsicGas` is a gas that is statically charged based on the configuration of the transaction, such as the datasize of the transaction.
* `ContractExecutionGas`, on the other hand, is a gas that is dynamically calculated due to the contract execution.

In here, we would focus on how `IntrinsicGas` is organized. For the `ContractExecutionGas`, the klvm documentation describes it in detail, so please refer [klvm docs](/content/klaytn/design/computation/klaytn-virtual-machine).

Coming back to `IntrinsicGas`, a transaction's `intrinsicGas` can be calculated by adding up the next four factors.

```
IntrinsicGasCost = KeyCreationGas + KeyValidationGas + PayloadGas + TxTypedGas
```

* `PayloadGas` is calculated based on the size of the data field in the tx.
* `KeyCreationGas` is calculated when the transaction registers new keys. Only applicable in `accountUpdate` transaction.
* `KeyValidationGas` is calculated based on the number of signatures.
* `TxTypedGas` is defined based on the transaction types.

Before we get into the detail, keep in mind that not all key types apply the keyGases (`KeyCreationGas` and `KeyValidationGas`).

| Key Type  | Are those keyGases applicable?     |
| --------- | ---------------------------------- |
| Nil       | No                                 |
| Legacy    | No                                 |
| Fail      | No                                 |
| Public    | Yes                                |
| MultiSig  | Yes                                |
| RoleBased | Depending on key types in the role |

### KeyCreationGas <a href="#keycreationgas" id="keycreationgas"></a>

The KeyCreationGas is calculated as `(number of registering keys) x TxAccountCreationGasPerKey (20000)`.\
Please Keep in mind that Public key type always has only one registering key, so the gas would be always 20000.

### KeyValidationGas <a href="#keyvalidationgas" id="keyvalidationgas"></a>

The KeyValidationGas is calculated as `(number of signatures - 1) x TxValidationGasPerKey(15000)`.\
Please keep in mind that Public key type always has only one signature key, so the gas would be always zero.

A Klaytn transaction can also have a feePayer, so the total KeyValidationGas is like this.

```
KeyValidationGas =  (KeyValidationGas for a sender) + (KeyValidationGas for a feePayer)
```

### PayloadGas <a href="#payloadgas" id="payloadgas"></a>

Calculating `PayloadGas` is simple. It is calculated as `(number_of_bytes_of_tx_input) x TxDataGas(100)`

### TxTypedGas <a href="#txtypedgas" id="txtypedgas"></a>

There are three types of transactions in klaytn; `base`, `feeDelegated`, and `feeDelegatedWithFeeRatio`.

For example,

* TxTypeValueTransfer is the `base` type of the valueTransaction transaction.
* TxTypeFeeDelegatedValueTransfer is a `feeDelegated` type of the valueTransfer transaction.
* TxTypeFeeDelegatedValueTransferWithRatio is a `feeDelegatedWithRatio` type of the valueTransfer transaction.

This is important when calculating TxTypedGas:

* First, check the TxType is `feeDelegated` or `feeDelegatedWithFeeRatio`.
  * If the TxType is `feeDelegated`, add `TxGasFeeDelegated(10000)` to TxTypedGas
  * If the TxType is `feeDelegatedWithFeeRatio`, add `TxGasFeeDelegatedWithRatio (15000)` to TxTypedGas
* Second, check the transaction creates contract or not.
  * If the transaction creates contract, add `TxGasContractCreation (53000)` to TxTypedGas.
  * Otherwise, add `TxGas (21000)` to TxTypedGas.

For example,

* If it's legacyTransaction and creates contract, the TxTypedGas would be `0 + TxGasContractCreation(53000)`.
* If it's TxTypeFeeDelegatedValueTransfer, the TxTypedGas would be `TxGasFeeDelegated(10000) + TxGas (21000)`
* If it's TxTypeFeeDelegatedSmartContractDeployWithRatio, the TxTypedGas would be `TxGasFeeDelegatedWithRatio (15000) + TxGasContractCreation (53000)`


# 트랜잭션 비용 (구 버전 문서)

{% hint style="success" %}
NOTE: This document contains the transaction fee used before the activation of the protocol upgrade. If you want the latest document, please refer to [latest document](/content/klaytn/design/transaction-fees).
{% endhint %}

The transaction fee of one transaction is calculated as follows:

```
Transaction fee := (Gas used) x (GasPrice)
```

As an easy-to-understand analogy in this regard, suppose you're filling up gas at a gas station. The gas price is determined by the refinery every day, and today's price is $2. If you fill 15L up, then you would pay $30 = 15L x $2/1L for it, and the $30 will be paid out of your bank account. Also, the transaction will be recorded in the account book.

Transaction fee works just the same as above. The network determines the gas price for every block. Suppose the gas price for the current block is 30 ston. If a transaction submitted by `from` account was charged 21000 gas, then 630000 ston = (21000 gas \* 30 ston) would be paid out of the `from` account. Also, the transaction will be recorded in the block, and it will be applied in the state of all blockchain nodes.

Summing it up again, this calculated transaction fee is subtracted from the sender's or fee payer's account. However, the fee can be deducted from the balance only if the transaction is created by klay\_sendTransaction/eth\_sendTransaction. Because the other transactions cannot change the state since they cannot be included in the block. They are just a simulation in some way.

This is an overall explanation of the transaction fee, and from this point, we would give a detailed explanation of how gas price is determined and how the gas is calculated.

## Unit Price Overview <a href="#unit-price-overview" id="unit-price-overview"></a>

`Unit price` is the price for a single gas. The unit price (also called `gas price`) is set in the system by the governance. It cannot be changed by user. The current value of the unit price can be obtained by calling the `klay.gasPrice` API.

In Ethereum, users set the gas price for each transaction, and miners choose which transactions to be included in their block to maximize their reward. It is something like bidding for limited resources. This approach has been working because it is market-based. However, the transaction cost fluctuates and often becomes too high to guarantee the execution.

To solve the problem, Klaytn is using a fixed unit price and the price can be adjusted by the governance council. This policy ensures that every transaction will be handled equally and be guaranteed to be executed. Therefore, users do not need to struggle to determine the right unit price.

### Transaction Validation against Unit Price <a href="#transaction-validation-against-unit-price" id="transaction-validation-against-unit-price"></a>

Klaytn only accepts transactions with gas prices, which can be set by the user, that are equal to the unit price of Klaytn; it rejects transactions with gas prices that are different from the unit price in Klaytn.

### Unit Price Error <a href="#unit-price-error" id="unit-price-error"></a>

The error message `invalid unit price` is returned when the gas price of a transaction is not equal to the unit price of Klaytn.

### 트랜잭션 교체 <a href="#transaction-replacement" id="transaction-replacement"></a>

Klaytn currently does not provide a way to replace a transaction using the unit price but may support different methods for the transaction replacement in the future. Note that in Ethereum, a transaction with a given nonce can be replaced by a new one with a higher gas price.

## Gas Overview <a href="#gas-overview" id="gas-overview"></a>

Every action that changes the state of the blockchain requires gas. While processing the transactions in a block, such as sending KLAY, using KIP-7 tokens, or executing a contract, the user has to pay for the computation and storage usage. The payment amount is decided by the amount of `gas` required.

`Gas` required is computed by adding up the next two gases;

* `IntrinsicGas` is a gas that is statically charged based on the configuration of the transaction, such as the datasize of the transaction.
* `ContractExecutionGas`, on the other hand, is a gas that is dynamically calculated due to the contract execution.

In here, we would focus on how `IntrinsicGas` is organized. For the `ContractExecutionGas`, the klvm documentation describes it in detail, so please refer [klvm docs](/content/klaytn/design/computation/klaytn-virtual-machine/klaytn-virtual-machine-previous).

Coming back to `IntrinsicGas`, a transaction's `intrinsicGas` can be calculated by adding up the next four factors.

```
IntrinsicGasCost = KeyCreationGas + KeyValidationGas + PayloadGas + TxTypedGas
```

* `PayloadGas` is calculated based on the size of the data field in the tx.
* `KeyCreationGas` is calculated when the transaction registers new keys. Only applicable in `accountUpdate` transaction.
* `KeyValidationGas` is calculated based on the number of signatures.
* `TxTypedGas` is defined based on the transaction types.

Before we get into the detail, keep in mind that not all key types apply the keyGases (`KeyCreationGas` and `KeyValidationGas`).

| Key Type  | Are those keyGases applicable?     |
| --------- | ---------------------------------- |
| Nil       | No                                 |
| Legacy    | No                                 |
| Fail      | No                                 |
| Public    | Yes                                |
| MultiSig  | Yes                                |
| RoleBased | Depending on key types in the role |

### KeyCreationGas <a href="#keycreationgas" id="keycreationgas"></a>

The KeyCreationGas is calculated as `(number of registering keys) x TxAccountCreationGasPerKey (20000)`.\
Please Keep in mind that Public key type always has only one registering key, so the gas would be always 20000.

### KeyValidationGas <a href="#keyvalidationgas" id="keyvalidationgas"></a>

The KeyValidationGas is calculated as `(number of keys - 1) x TxValidationGasPerKey(15000)`.\
Please keep in mind that Public key type always has only one signature key, so the gas would be always zero.

A Klaytn transaction can also have a feePayer, so the total KeyValidationGas is like this.

```
KeyValidationGas =  (KeyValidationGas for a sender) + (KeyValidationGas for a feePayer)
```

### PayloadGas <a href="#payloadgas" id="payloadgas"></a>

`PayloadGas` is calculated as below.

```
# legacy-typed transaction
PayloadGas = number_of_zero_bytes x TxDataZeroGas (4) + number_of_nonzero_bytes x TxDataNonZeroGas (68)`

# non legacy-typed transaction
PayloadGas = number_of_bytes * TxDataGas (100)
```

### TxTypedGas <a href="#txtypedgas" id="txtypedgas"></a>

There are three types of transactions in klaytn; `base`, `feeDelegated`, and `feeDelegatedWithFeeRatio`.

For example,

* TxTypeValueTransfer is the `base` type of the valueTransaction transaction.
* TxTypeFeeDelegatedValueTransfer is a `feeDelegated` type of the valueTransfer transaction.
* TxTypeFeeDelegatedValueTransferWithRatio is a `feeDelegatedWithRatio` type of the valueTransfer transaction.

This is important when calculating TxTypedGas:

* First, check the TxType is `feeDelegated` or `feeDelegatedWithFeeRatio`.
  * If the TxType is `feeDelegated`, add `TxGasFeeDelegated(10000)` to TxTypedGas
  * If the TxType is `feeDelegatedWithFeeRatio`, add `TxGasFeeDelegatedWithRatio (15000)` to TxTypedGas
* Second, check the transaction creates contract or not.
  * If the transaction creates contract, add `TxGasContractCreation (53000)` to TxTypedGas.
  * Otherwise, add `TxGas (21000)` to TxTypedGas.

For example,

* If it's legacyTransaction and creates contract, the TxTypedGas would be `0 + TxGasContractCreation(53000)`.
* If it's TxTypeFeeDelegatedValueTransfer, the TxTypedGas would be `TxGasFeeDelegated(10000) + TxGas (21000)`
* If it's TxTypeFeeDelegatedSmartContractDeployWithRatio, the TxTypedGas would be `TxGasFeeDelegatedWithRatio (15000) + TxGasContractCreation (53000)`


# 클레이튼의 네이티브 코인 - KLAY

## KLAY <a href="#klay" id="klay"></a>

KLAY는 Klaytn에서 전송 가능한 주요 내부 암호화폐입니다. Klay는 스마트 컨트랙트 작성 및 실행 또는 KLAY를 전송할 때 트랜잭션 수수료를 지불하기 위해 사용됩니다.

KLAY는 Klaytn이라는 분산형 애플리케이션 플랫폼을 작동시키기 위해 필수적인 연료 역할을 합니다. Klay는 요청된 연산을 처리하는 컨센서스 노드(CNs)에 플랫폼의 클라이언트가 비용을 지불할 때 사용하는 수단입니다. To put it another way, KLAY is an incentive; it ensures that developers write high-quality applications (wasteful code costs more) and that the network remains healthy (CNs are compensated for the resources they contribute).

## KLAY의 단위 <a href="#units-of-klay" id="units-of-klay"></a>

Klaytn은 KLAY에 다음과 같은 단위 시스템을 사용합니다.

* `peb`는 가장 작은 화폐 단위입니다.
* `ston`은 `Gpeb`의 별명으로 편의를 위해 만들어졌습니다.
* `KLAY`는 10^18 peb입니다.

| 단위    | peb 가치    | peb                                       |
| ----- | --------- | ----------------------------------------- |
| peb   | 1 peb     | 1                                         |
| kpeb  | 10^3 peb  | 1,000                                     |
| Mpeb  | 10^6 peb  | 1,000,000                                 |
| Gpeb  | 10^9 peb  | 1,000,000,000                             |
| ston  | 10^9 peb  | 1,000,000,000                             |
| uKLAY | 10^12 peb | 1,000,000,000,000                         |
| mKLAY | 10^15 peb | 1,000,000,000,000,000                     |
| KLAY  | 10^18 peb | 1,000,000,000,000,000,000                 |
| kKLAY | 10^21 peb | 1,000,000,000,000,000,000,000             |
| MKLAY | 10^24 peb | 1,000,000,000,000,000,000,000,000         |
| GKLAY | 10^27 peb | 1,000,000,000,000,000,000,000,000,000     |
| TKLAY | 10^30 peb | 1,000,000,000,000,000,000,000,000,000,000 |

#### KLAY 단위와 관련된 API <a href="#apis-related-to-klay-units" id="apis-related-to-klay-units"></a>

`klay.toPeb`와 `klay.fromPeb`은 KLAY 단위 변환을 위해 사용되는 편리한 API입니다.

```
$ ./klay attach data/dd/klay.ipc
...
> klay.fromPeb(25, "peb")
"25"
> klay.fromPeb(25, "Gpeb")
"0.000000025"
> klay.fromPeb(25, "ston")
"0.000000025"
> klay.fromPeb(25, "KLAY")
"0.000000000000000025"
> klay.toPeb(25, "peb")
"25"
> klay.toPeb(25, "ston")
"25000000000"
> klay.toPeb(25, "KLAY")
"25000000000000000000"
```

`klay.toPeb`이나 `klay.fromPeb`에 아래와 같이 부적합한 단위를 기입하면 지원되는 KLAY 단위의 목록을 볼 수 있습니다.

```
> klay.toPeb(1, "something-does-not-exist")
Error: This unit doesn't exist, please use one of the following units
(이 단위는 존재하지 않습니다. 아래의 목록 중에 하나를 사용해 주세요.)
"noKLAY": "0"
"peb": "1"
"kpeb": "1000"
"Mpeb": "1000000"
"Gpeb": "1000000000"
"ston": "1000000000"
"uKLAY": "1000000000000"
"mKLAY": "1000000000000000"
"KLAY": "1000000000000000000"
"kKLAY": "1000000000000000000000"
"MKLAY": "1000000000000000000000000"
"GKLAY": "1000000000000000000000000000"
"TKLAY": "1000000000000000000000000000000"

    at web3.js:2170:19
    at web3.js:2255:49
```


# 토큰 이코노미

## Overview <a href="#overview" id="overview"></a>

클레이튼의 토큰 이코노미는 플랫폼의 생태계 운영, 성장 계획, 전략적 투자를 지속가능하게 지원하기 위한 구조를 갖추도록 설계되었습니다. 많은 공개 블록체인 프로젝트들의 토큰 이코노미는 네트워크 유지라는 기술적 측면에만 초점을 맞추면서 노드 운영자(채굴자 또는 블록 생산자)에게만 유인을 제공합니다. 그러나 이는 네트워크의 확장에 기여하거나 장기 성장에 투자하는 다른 참여자들에게 유인을 제공하는 중요성을 간과하는 것입니다. 클레이튼의 토큰 이코노미는 폭넒은 영역의 참여자들의 더 다양한 형태로 기여하고 이에 대해 보상을 받을 수 있도록 설계되었습니다. 또한, 블록체인 노드 운영 외에도 외에도 미래 성장 계획이나 전략적으로 기획된 투자 프로젝트를 지원하기 위해 지속적으로 재원을 공급할 수 있는 구조를 가지고 있습니다.

## 펀딩 구조(Funding Structure) <a href="#funding-structure" id="funding-structure"></a>

클레이튼의 펀딩 구조는 클레이튼 네트워크의 블록 생성과 함께 지속적으로 운영됩니다. 모든 신규 블록에서 발행된 KLAY, 그리고 블록(총칭 "블록 보상" )에 사용된 트랜잭션 수수료의 합계는 사전 결정된 비율에 따라 다음 세 개의 계정에 집계 및 배포됩니다.

* Klaytn Governance Council (GC) Reward:
  * GC Block Proposer Reward: 10%
  * GC Staking Award: 40%
* Klaytn Community Fund (KCF): 30%
* Klaytn Foundation Fund (KFF): 20%

6.4 KLAY will be minted for every new block. This implies that approximately 200 million KLAY will be minted annually, which is equivalent to 2% annual inflation against the 10 billion KLAY issued at genesis (the annual inflation rate is subject to change through the Klaytn Governance Process). 트랜잭션 수수료는 OPcode당 부과되며, 트랜잭션 수수료 표에 따라 책정됩니다. 트랜잭션 수수료 표에 대해서 더 자세한 정보를 알고 싶으시다면 [트랜잭션 수수료](/content/klaytn/design/transaction-fees)를 참고해주세요.

## 클레이튼 거버넌스 카운슬 보상 <a href="#klaytn-governance-council-reward" id="klaytn-governance-council-reward"></a>

클레이튼 거버넌스 카운슬은 코어 셀 운영자(CCOs)들의 집단입니다. 카운슬 구성원은 코어 셀 (CCs)을 유지해야 할 책임이 있으며, 이 카운슬은 클레이튼 생태계에서 기본 인프라 제공을 담당하는 필수 기관이됩니다. 카운슬 멤버가 되려면 클레이튼 거버넌스 프로세스에서 자격 검토를 받아야하며, 5백만 KLAY라는 최소 스테이킹 조건을 충족해야 합니다. Klaytn 거버넌스 카운슬 보상은 카운슬 멤버들이 Klaytn 생태계의 안정적인 기반이 될 수 있도록 유인을 제공하는 구조입니다.

### 클레이튼 거버넌스 카운슬 보상 메커니즘 <a href="#klaytn-governance-council-reward-mechanism" id="klaytn-governance-council-reward-mechanism"></a>

모든 블록마다 무작위로 선정된 카운슬 멤버로 이루어진 위원회가 구성됩니다. 각 위원회는 한 멤버가 제안자(Proposer) 역할을 할당받습니다. 다른 모든 위원회 위원은 검증자(Validator)의 역할을 맡습니다. 블록이 성공적으로 생성되어 클레이튼 블록체인에 추가되면, 해당 블록의 제안자에게는 블록 보상의 100%가 제공됩니다. 카운슬 멤버가 제안자로 선정될 확률은 회원이 스테이크한 KLAY의 양에 비례합니다. 즉, 더 많은 KLAY를 스테이크 할수록 멤버가 제안자로 선정되어 블록보상을 받을 가능성이 커집니다.

요구사항인 최소 500만 KLAY 스테이킹이 충족되는 한 클레이튼 거버넌스 카운슬 멤버는 자신의 KLAY를 자유롭게 스테이크하거나 언스테이크(unstake) 할 수 있습니다. 스테이킹 정보는 86,400블록마다 업데이트되며, 새로 스테이크 된 KLAY는 스테이킹이 완료된 후 두 번의 업데이트 주기 이후에 효력이 생깁니다. 스테이크 된 KLAY를 인출하는 일은 악의적인 멤버가 즉시 빠져나가지 못하도록 일주일 정도 지연됩니다.

많이 투자한 소규모 그룹의 카운슬 멤버들이 클레이튼 거버넌스 카운슬 보상을 독점하는 것을 막기 위해 지니 계수(Gini coefficient)가 이용되어 스테이크 된 Klay의 유효 수량을 조정할 수 있습니다. 적용 공식은 다음과 같습니다. G가 거버넌스 카운슬의 KLAY 스테이킹 배분의 지니 계수를 나타냅니다.

* *조정된 스테이킹 양(Adjusted staking amount) = (카운슬 멤버의 스테이킹 양)^(1/1+G)*

### 잘못된 행동을 하는 카운슬 멤버에 대한 처벌 <a href="#penalty-for-misbehaving-council-members" id="penalty-for-misbehaving-council-members"></a>

카운슬 멤버는 아래와 같은 잘못된 행동을 하면 처벌의 대상이 될 수 있습니다. 앞으로 클레이튼 거버넌스 프로세스를 통해 더 많은 페널티 규칙이 수립되고 수정될 수 있습니다.

Safety Failure를 일으키는 경우:

* 제안자로 선택된 카운슬 멤버는 같은 높이에 두 개 이상의 블록을 만들 수 없습니다.
* 제안자로 선정된 카운슬 멤버는 의도적으로 특정 트랜잭션을 제외할 수 없습니다.

Liveness Failure를 일으키는 경우:

* 제안자로 선택된 카운슬 멤버는 유효한 블록을 생성해야 합니다.
* 검증자로 선정된 카운슬 멤버는 제안자가 제안한 블록을 검증해야합니다.

## Klaytn Community Fund <a href="#klaytn-community-fund" id="klaytn-community-fund"></a>

The Klaytn Community Fund (KCF) was established to support Klaytn's mission of enabling greater transparency and verifiability. It's important to keep in mind that the former Klaytn Growth Fund (KGF) and Klaytn Improvement Reserve (KIR) have merged to become the new Klaytn Community Fund (KCF).

The Klaytn Community Fund will be used to fund activities that improves the Klaytn ecosystem, such as:

1. **Rewarding Proof of Contribution**: The KCF will provide follow-up support, such as gas fee support to projects that have made significant on-chain contributions to the Klaytn ecosystem among services that have already been developed.
2. **Building our Developer Community**: The KCF will support various initiatives including hackathons, development education programs, collaborative research with the industry, and collaboration with various DAOs to foster and grow the Klaytn developer community.
3. **Fostering Ecosystem Services and Infrastructure**: The KCF will support essential ecosystem infrastructure, alongside the development of services with clear utility and provide marketing support.
4. **Klaytn Eco Fund Indirect Investment**: The KCF will make indirect mid-to long-term investments by entrusting specialized crypto VCs, and most of the profits generated upon subsequent investment recovery will be returned to the Klaytn ecosystem.

The administration of the Klaytn Community Fund follows a process in which the GC reviews and approves the use of funds in public forums on [Klaytn Square](https://square.klaytn.foundation/Home). The Foundation will submit a budget proposal for each category to the GC for approval. Within the approved budget, each specific use will be reviewed and approved again by the GC. In the meantime, the KCF is currently being run as a [pilot program](https://klaytn.foundation/kcf-grant-pilot/) and interested parties can visit the [Klaytn Governance Forum](https://govforum.klaytn.foundation/t/operational-procedures-of-the-kcf-grant-program-pilot/288) for more details about the program.

## Klaytn Foundation Fund <a href="#klaytn-foundation-fund" id="klaytn-foundation-fund"></a>

Klaytn Foundation Fund (KFF) is an operational fund that will focus on this two main categories:

1. **Ecosystem Support**: This includes providing minor financial assistance, securing new GC members, liquidity provisions, and developing / funding services led by the Foundation.
2. **Foundation Operations**: This includes operating expenses such as development, accounting, infrastructure operations, marketing, and labor, as well as financial management and investment attraction costs.

Similar to KCF, KFF will be executed autonomously and transparently after obtaining approval from the GC via on-chain voting.

For more information, kindly read this [article](https://medium.com/klaytn/klaytn-tokenomics-optimization-governance-proposal-securing-a-sustainable-verifiable-token-1efd2a49b04e).


# 거버넌스

## Overview <a href="#overview" id="overview"></a>

### 클레이튼 거버넌스: 탈중앙화로 가는 첫 걸음 <a href="#klaytn-governance-taking-the-first-step-to-decentralization" id="klaytn-governance-taking-the-first-step-to-decentralization"></a>

클레이튼 거버넌스 카운슬은 다양한 거버넌스 사안에 대한 결정권이 있습니다. 그 신뢰성을 확보하기 위해 거버넌스 카운슬 초기 멤버들은 신뢰받는 기업들에 한정되었습니다. 플랫폼의 발전 및 안정화 단계의 효과성을 위한 선택이었습니다. 클레이튼은 31곳의 거버넌스 카운슬 멤버와의 협력과 클레이튼 메인넷의 원활한 운영을 통해 이 단계에 도달할 수 있었습니다.

클레이튼은 클레이튼 거버넌스가 우리 세계의 변화와 정렬된 클레이튼의 성장을 이끌어야 한다고 믿습니다. 이 세계의 주된 변화 중 하나가 바로 메타버스의 성장에서 비롯됩니다. 기술 진보는 더 메타버스화된 세상을 불러오고 있습니다. 특히 비전통적인 탈중앙화된 자율 조직(DAO)과 빌더들의 영향력이 날로 강해지고 있습니다. 중앙화된 구조 없이 스마트 컨트랙트 상에서 작동하는 조직인 DAO는 메타버스의 핵심 주체가 될 것입니다. 빌더들은 메타버스의 운영과 성장에 기여하면서 더 큰 영향력을 가지게 될 것이다.

우리는 변화하는 세상에 더 잘 적응하기 위해 거버넌스 구조를 재편성하고 있습니다. 클레이튼은 클레이튼 거버넌스 카운슬 멤버십을 전통적인 기업 외에 앞서 언급한 비전통적 주체들에게도 개방할 것입니다.

스테이킹 기반 거버넌스 모델의 도입과 클레이튼 투표 메커니즘에서 지니 계수의 제거를 통해 클레이튼은 커뮤니티의 지지를 많이 받는 거버넌스 참여자들이 자신의 선호에 따라 클레이튼을 만들어 나갈 수 있도록 해줍니다. 메타버스화된 세상에서 적절한 결정을 내릴 수 있는 주체들이 클레이튼 GC에서 더 많은 영향력을 지니게 될 것입니다. 우리는 DAO와 빌더들이 해당 영역의 리더가 될 것이라 믿습니다.

메타버스화 수준이 임계치를 넘으면 클레이튼 거버넌스는 다양한 유형의 엔티티로 완전히 탈중앙화될 것입니다. 궁극적으로 클레이튼은 온체인 메커니즘을 통해 DAO들이 클레이튼 커뮤니티의 목소리를 전달할 수 있는 플랫폼이자 DAO들의 DAO로 진화할 것입니다.

## 거버넌스 사항 <a href="#governance-topics" id="governance-topics"></a>

거버넌스 구조를 통해 결정할 수 있는 주요 안건은 다음 세 가지 영역이며, 추가 의사 결정이 필요한 안건은 정기 회의 또는 임시 회의에 상정하여 검토할 수 있습니다. 클레이튼 거버넌스 카운슬은 클레이튼의 성장을 위해 최선의 결정을 내려야 합니다.

* **기술**
  * 플랫폼의 기술적 업데이트와 관련된 사항. 여기에는 블록체인의 기본 구조(예: 계정 구조), 새로운 기능(예: L2 솔루션) 또는 소프트웨어 업데이트 일정에 대한 이슈가 포함됩니다.
* **Economy**
  * KLAY 추가 발행 및 분배 구조, 트랜잭션 수수료 변경, Klaytn 개선 준비금(KIR) 지출 승인 등과 관련된 이슈가 이 범주에 포함됩니다.
* **Governing Rule**
  * 거버넌스 주체와 프로세스, 거버넌스 기관의 책임과 권한에 대한 규칙이 이 범주에 포함됩니다.

## 거버넌스 프로세스 <a href="#governance-process" id="governance-process"></a>

클레이튼은 기본적으로 거버넌스 프로세스가 프로토콜(On-chain) 내에서 이루어지는 것을 목표로 합니다. 이 과정을 통해 투표가 블록체인에 기록되고, 투표 후 결과가 실행됩니다. 플랫폼이 성장함에 따라 더 많은 사안이 온체인 거버넌스를 통해 처리될 것입니다.

### 일반 거버넌스 절차(General Governance Process) <a href="#general-governance-process" id="general-governance-process"></a>

초기 거버넌스 프로세스는 제안서 소개, 자문위원의 의견서 제출, 거버넌스 카운슬 멤버들의 투표, 투표 결과에 따른 다양한 후속 절차의 순서로 진행됩니다.

제안을 상정할 권한이 있는 사람은 제안을 상정함으로써 각 제안을 투표에 부칠 수 있습니다. 제안서가 상정되면 자문위원은 제안서에 대한 전문적인 분석을 수행하고 그 결과를 담은 의견서를 제출해야 합니다.

클레이튼 거버넌스 초기 단계에서 클레이튼 거버넌스 카운슬 멤버들은 도입된 제안에 대해 투표권을 가지며, 자문위원들의 의견서를 참고하여 최선의 선택이라고 생각되는 사항에 투표하게 될 것입니다. 투표 수가 임계치를 넘으면 제안이 통과되고, 그렇지 않으면 제안이 기각됩니다. 초기 단계에서는 투표 정차가 클레이튼 재단에서 진행하는 토론 절차로 대체될 수 있습니다. 승인된 제안에 대한 후속 조치는 의장이 주도하며, 의장은 임기 동안 협의회에서 통과된 모든 제안을 실행할 책임이 있습니다.

### Klaytn Improvement Reserve Review Process <a href="#klaytn-improvement-reserve-review-process" id="klaytn-improvement-reserve-review-process"></a>

KIR 제안서 심사는 거버넌스 카운슬 위원들의 투표를 통해 결정되며, 위원 과반수 이상이 반대(부결)하면 제안서는 부결됩니다. For more details on the KIR Proposal review, refer to the following.

![kir\_process](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-805ca673f13e971b89752d987544004d94660673%2Fkir_process.png?alt=media\&token=a0d3a3bb-6977-499e-8147-0b9dcf1c36a9)

자세한 내용은 [KIR 포럼](https://kir.klaytn.foundation/)에서 확인하세요.

## Governance Roadmap <a href="#governance-roadmap" id="governance-roadmap"></a>

거버넌스에 참여하는 주체들은 개인의 이익보다는 클레이튼의 장기적인 이익을 고려하여 행동해야 하며, 거버넌스 프로세스에 적극적으로 참여해야 합니다. 또한 클레이튼 거버넌스 카운슬 멤버로서 네트워크에 기여하는 모든 참여자는 플랫폼 요구 사항보다 더 많은 컴퓨팅 자원(computing resources)을 확보해야 하며, 자체적으로 또는 제3자로부터 일정량의 KLAY를 스테이킹해야 합니다. 클레이튼 재단은 플랫폼 개발과 안정화의 원활한 운영을 위해 초기 개발 단계에서 거버넌스와 관련된 많은 역할을 맡게 될 것입니다. 그러나 앞으로는 의사 결정 과정에서 다른 기관의 역할이 점차 커질 것이며, 독립적으로 참여할 수 있는 권리를 갖게 될 것입니다.

* **개발 단계(Development Phase)**: 메인넷 출시 후 초기 개발 단계에서는 매개변수 조정, 새로운 기능 개발 등이 신속하게 이루어져야 합니다. 이를 위해 클레이튼 거버넌스 카운슬 멤버, 서비스 제공자, 커뮤니티 멤버들의 의견을 수렴하여 많은 이슈를 결정할 것입니다. 초기 안정화를 위해 클레이튼 재단이 의사결정 과정을 주도할 것입니다. 또한 결정된 모든 사안은 대중과 투명하게 공유됩니다.
* **안정화 단계(Stabilization Phase)**: 클레이튼 거버넌스 카운슬은 많은 제안에 대한 관리 권한을 가지고 있으며, 이 단계는 2021년 1월부터 점진적으로 시작될 예정입니다. 플랫폼 개발에 관한 사항이나 클레이튼 생태계 전반에 직접적인 영향을 미치는 사항과 같은 특별한 사안의 경우, 클레이튼 재단이 논의와 실행을 독려할 수 있습니다.
* **탈중앙화 단계(Decentralization Phase)**: 안정화 기간 이후에는 DAO 및 빌더와 같은 다양한 비전통적 주체(non-traditional entities)가 의사결정 과정에 참여하여 추가적인 의견을 제시할 수 있습니다. 탈중앙화 단계는 서로 다른 운영 규칙과 참가자를 통한 여러 단계를 통해 점진적으로 달성될 수 있습니다.


# 다중 채널

Klaytn 노드는 **다중 채널**로 운영될 수 있습니다.

노드가 다중 채널로 실행될 경우 커뮤니케이션을 위해 두 개의 포트가 설치됩니다. 단일 채널로 노드가 실행될 시, 하나의 포트만 설치됩니다. 두 다중 채널 노드가 연결될 때 두 개의 포트가 사용됩니다. 그 외의 경우에는 하나의 포트가 사용됩니다.

다중 채널 노드는 `--multichannel` 플래그를 통해 활성화될 수 있습니다. If you use [`kend`](/content/installation-guide/deployment/endpoint-node/installation-guide/startup-the-en), multi-channel is enabled by default due to the statement `MULTICHANNEL=1` in [`kend.conf`](/content/installation-guide/deployment/endpoint-node/installation-guide/configuration). 다중 채널을 비활성화하기 위해서는 선언문을 `MULTICHANNEL=0`로 대체하면 됩니다. 특정 포트를 사용해 노드를 운영하고 싶다면 `port`와 `subport` 플래그가 사용될 수 있습니다. 연결되는 피어의 포트 값을 특정하고 싶다면 [KNI](/content/klaytn/design/kni)를 확인해세요.

## 구조 <a href="#architecture" id="architecture"></a>

![Multi-Channel Server](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-f96ec73881c10086d97d0a8867885a7b9867e3c3%2Fmultichannel.png?alt=media\&token=a997bcb2-8d77-4c19-be78-2c6eb3a4c050)

위의 그림은 두 다중 채널 노드 간의 연결을 보여줍니다. 메인포트(A)와 서브포트(B) 두 포트는 다른 메시지를 전달합니다.

* **메인포트**(A)는 블록과 합의 프로토콜 관련 메시지 전달에 사용됩니다.
  * 블록 메시지는 해시, 헤더, 바디, 그리고 블록 영수증에 대한 요청과 응답을 포함합니다.
  * 합의 메시지는 Request, Preprepare, Prepare, Commit, 그리고 RoundChange 등을 포함합니다. 이 메시지들의 의미는 [PBFT](/content/klaytn/design/consensus-mechanism#pbft-practical-byzantine-fault-tolerance)에서 찾을 수 있습니다.
* **서브포트**(B)는 트랜잭션 메시지 전달을 위한 것입니다.

![Single Channel Server](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-eddbc65e760c775448ba537fe9e290abe33b63a0%2Fsinglechannel.png?alt=media\&token=7d9dd0df-52cc-4879-b98a-cf28dc2248f5)

이 그림은 두 단일 채널 노드 간, 또는 단일 채널 노드와 다중 채널 노드 간의 연결을 나타냅니다. 이 경우, 블록, 트랜잭션, 합의 프로토콜에 관련된 모든 메시지들은 동일한 포트를 통해 전달됩니다.

## 포트 <a href="#multichannel-port" id="multichannel-port"></a>

KNI에서 포트 번호를 설정하고 싶다면 [KNI 스킴](/content/klaytn/design/kni)을 참고하세요.

* 단일 채널 : 단일 채널 노드는 하나의 포트를 사용합니다 (기본값은 32323입니다).
* 다중 채널: 다중 채널 노드는 두 개의 포트를 사용합니다. 이 포트들은 `port`와 `subport`로 특정될 수 있습니다. Klaytn에서는 `port`와 `subport`의 기본값이 각각 32323과 32324입니다.
  * 다중 채널 노드에 연결할 때는 `subport`를 설정하지 않아도 됩니다. 이 경우 처음에 Klaytn 노드는 단일 채널을 사용해 연결을 하려고 할 것입니다. 핸드셰이크 과정에서 실제 피어의 포트 번호가 드러납니다. 피어가 다중 채널 노드라면, 지속 중인 연결은 취소되고 업데이트된 포트로 재연결될 것입니다.


# KNI

\*\*KNI (Klaytn Network Identifier)\*\*는 Klaytn 노드를 식별하기 위한 URL 스킴입니다. 신택스는 다음과 같습니다.

```
kni://<nodeID>@<hostname>:<port>?subport=<subport>&discport=<discport>
```

![KNI scheme](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-d288a716d59b603ec96269314a7a5d84a6a57edb%2Fkni_scheme.png?alt=media\&token=f0291f1f-ebef-4d0f-953a-6a754c3724ff)

**nodeID**는 노드의 개인키에 상응하는 512비트 공개키입니다. P2P 네트워크에서 피어들과의 소통을 검증하는 데 사용됩니다.

**hostname**은 `@`와 `:` 사이에 위치한 노드의 주소를 나타냅니다. 주소 형식은 다음 중 하나를 취합니다.

* IPv4 dotted decimal (`192.0.2.1`)
* IPv6 (`[2001:db8::68]`)
* IPv4-mapped IPv6 (`[2001:db8:3c4d:15::abcd:ef12]`)
* 도메인명 (`your.node.com`)

**port**는 TCP를 통해 피어 노드들과 연결하기 위해 사용됩니다. Klaytn의 경우 `port`의 기본값은 `32323`이며, `subport`의 기본값은 `32324`입니다. `subport`의 기본값은 `kend.conf`에 `port + 1`라고 설정되어 있습니다. TCP 수신 대기(listening) 포트의 수에 따라 Klaytn은 두 종류의 [연결](/content/klaytn/design/multiport)을 제공합니다.

**discport**는 알려진 이웃들이 인접한 Klaytn 노드인지 확인하고, 새로운 연결을 위해 이웃 주소를 가져올 때 쓰입니다. 이것은 UDP port라는 점을 유의하십시오. 기본값으로 UDP port, 또는 `discport`는 TCP port와 같은 port를 사용합니다. 노드가 `discport`에 다른 port를 사용한다면, `discport` 쿼리 파라미터를 통해 지정될 수 있습니다.

이하의 두 URL은 IP 주소가 `10.0.0.1`, TCP listening port가 `32323`와 `32324`인 KNI 예시입니다. `discport`가 생략될 시 UDP port `32323`로 지정되며, 이는 `port` 값과 동일합니다.

```
kni://a979...163c@10.0.0.1:32323                 # either single-channel or multi-channel peer with omitted subport
kni://a979...163c@10.0.0.1:32323?subport=32324   # multi-channel peer
```

이하의 두 URL은 `discport`가 `30301`인 노드의 KNI의 예시입니다.

```
kni://a979...163c@10.0.0.1:32323?discport=30301                 # either single-channel or multi-channel peer with omitted subport
kni://a979...163c@10.0.0.1:32323?subport=32324&discport=30301   # multi-channel peer
```

If you want to know how to generate a KNI of a node, please refer to [Node Key & Node URI Creation](/content/installation-guide/deployment/core-cell/installation-guide/before-you-install#node-key-node-uri-creation). The KNI scheme is used in node discovery protocol, [setting `static-nodes.json` file](/content/installation-guide/deployment/core-cell/installation-guide/proxy-node-setup/configuration#install-static-nodes-json), [addPeer API](/content/dapp/json-rpc/api-references/admin#admin_addpeer), [bootnodes option](/content/operation-guide/configuration#properties) and etc.


# 확장성 솔루션

### 서비스체인 <a href="#service-chain" id="service-chain"></a>

클레이튼의 서비스체인은 클레이튼의 메인체인과는 분리된 독립적인 보조 블록체인입니다. 서비스체인은 개별 dApp에 맞도록 특별하게 노드 설정을 할 수 있습니다. 또한, 맞춤형 보안 레벨 설정을 하거나 메인체인에서는 불편하거나 불가능한 높은 처리량을 가진 블록체인을 구현할 수 있습니다.

완전히 탈중앙화된 스케일링 솔루션이 존재하지만 Challenge나 Exit 같은 어려운 인터페이스나 비즉각적 완결성 문제 때문에 클레이튼의 서비스체인은 다른 접근법을 취하였습니다. 서비스체인은 더 나은 사용성, 즉각적인 완결성, 높은 성능 및 가용성을 위해 완전한 탈중앙화를 일부 희생하였습니다.

클레이튼 서비스체인은 다양한 서비스별 목표를 위해 사용될 수 있으며 데이터 앵커링이나 밸류 트랜스퍼 같은 여러 가지 이유로 메인체인과 연결될 수 있습니다. (데이터 앵커링: 노드 수가 적어 서비스체인의 보안이 저하된 것을 보완하기 위해 서비스체인의 블록 해시를 메인 체인으로 정기적으로 저장하는 일 / 밸류 트랜스퍼: KLAY나 dApp에서 발행한 토큰의 체인 간 전송)

### 네트워크 <a href="#network" id="network"></a>

클레이튼 메인체인에 연결된 서비스체인들을 통칭하여 서비스체인 네트워크라고 부릅니다. 서비스체인과 메인체인의 연결 방법은 추후 달라질 수 있습니다.

![그림 1. Klaytn 메인체인과 서비스체인](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-804cc595e4515b5b602cf8fdc86369dd953c1604%2Fmainchain_servicechain.png?alt=media)

그림 1은 다양한 비즈니스 요구를 충족하기 위해 사용되는, 클레이튼 메인체인과 연결되어 클레이튼 네트워크를 확장하는 서비스체인들의 네트워크 토폴로지를 보여줍니다.

![그림 2. Main/Sub-Bridge Model을 이용해 연결된 메인체인과 서비스체인](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-94ffe69bfb238df5d7c2c228421f22d6f798ff49%2Fsc_connection.png?alt=media)

그림 2는 서비스체인의 기능인 main/sub-bridge 모델을 이용하여 클레이튼 메인체인의 EN(Endpoint Node)과 직접적으로 연결되어있는 SCN(Service Chain Consensus Node)의 예를 보여줍니다.

### Features <a href="#features" id="features"></a>

서비스체인은 데이터 무결성 메커니즘을 제공하고, 서로 다른 체인 간의 토큰 전송을 지원함으로써 Klaytn을 확장합니다.

#### 데이터 앵커링 <a href="#data-anchoring" id="data-anchoring"></a>

데이터 무결성을 위해 서비스체인의 블록 해시를 메인체인에 특별한 트랜잭션을 이용해 자동으로 저장할 수 있습니다. 이 데이터 앵커링을 이용하여 서비스체인에 올라간 데이터가 바뀌지 않았음을 사용자들에게 확신시킬 수 있습니다.

#### Value Transfer <a href="#value-transfer" id="value-transfer"></a>

서비스 제공자들(SPs)이 쉽게 서비스 사용자들을 체인간 이전할 수 있도록 KLAY나 dApp을 통해 만들어진 토큰 등의 체인간 전송을 지원합니다. 사용자는 bridge contract라고 불리는 특별한 컨트랙트에 트랜잭션을 보냄으로써 다른 체인으로 토큰을 쉽게 이전할 수 있습니다.


# Getting Started

Klaytn에 익숙해지도록 해봅시다 이 장이 Klaytn dApp 여행의 출발점입니다.


# Deploying Smart Contract Using Foundry

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-e7446980fdd28d30e101576ace9f2d1937fbfeb6%2Fklaytn-foundry.png?alt=media)

## Introduction

Foundry는 Rust로 작성된 스마트 컨트랙트 개발 프레임워크로, 개발자들이 계약을 관리하고 컴파일하고, 테스트를 실행하고, 계약을 배포하며, 커맨드 라인을 통해 솔리디티 스크립트로 네트워크와 상호 작용할 수 있게 해줍니다.

Foundry는 다음과 같이 네 가지 주요 CLI 도구로 구성되어 있으며, 이를 통해 빠르고 모듈식 스마트 계약 개발이 가능합니다:

* [Forge](https://github.com/foundry-rs/foundry/tree/master/forge): Forge를 사용하여 스마트 컨트랙트를 배포하고, 테스트하고, 컴파일할 수 있습니다.
* [Cast](https://github.com/foundry-rs/foundry/tree/master/cast): Cast는 EVM 스마트 컨트랙트와 상호 작용하는 것을 간단하게 만들었습니다. Cast는 체인 데이터를 얻는 것, 트랜잭션을 보내는 것과 그 외의 것들도 포함합니다.
* [Anvil](https://github.com/foundry-rs/foundry/tree/master/anvil): 로컬 노드를 구동해야 하나요? Anvil은 Foundry에서 제공하는 로컬 노드 환경입니다.
* [Chisel](https://github.com/foundry-rs/foundry/blob/master/chisel): 빠르고 유용하며 자세한 솔리디티 REPL입니다.

여러분은 가이드를 통해서 아래 사항을 진행할 수 있습니다:

* 간단한 Foundry 프로젝트를 생성합니다.
* Foundry를 사용하여 샘플 스마트 컨트랙트를 컴파일하고 테스트합니다.
* Foundry를 사용하여 Klaytn Baobab 네트워크에 스마트 컨트랙트를 배포합니다.
* Cast와 Anvil을 사용하여 메인넷을 포크하는 방법을 탐색합니다.

## Pre-requisites

아래 내용은 튜토리얼을 따르기 위한 필수 요구 사항입니다:

* 코드 에디터: [VS-Code](https://code.visualstudio.com/download)와 같은 소스 코드 에디터
* [MetaMask](https://docs.klaytn.foundation/dapp/tutorials/connecting-metamask#install-metamask): 컨트랙트를 배포하고, 트랜잭션에 서명하고, 컨트랙트와 상호 작용하는 데 사용됩니다.
* RPC Endpoint: 지원되는 [Endpoint Providers](https://docs.klaytn.foundation/content/dapp/json-rpc/public-en) 중 하나에서 이를 얻을 수 있습니다.
* [Faucet](https://baobab.wallet.klaytn.foundation/faucet)에서 테스트 KLAY 받기: 충분한 KLAY로 계정에 자금을 입금합니다.
* [Rust](https://www.rust-lang.org/tools/install)와 [Foundry](https://github.com/foundry-rs/foundry#installation)를 설치합니다.

## Setting Up Your Development Environment

Foundry 설치가 성공적인지 확인하려면 아래 명령어를 실행하세요:

```bash
forge -V
```

**Output**

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-ebcdb8b048816e82c4b026ba4a006be331f2e38a%2Fforge-version.png?alt=media)

Foundry를 성공적으로 설치한 후, 이제 foundry에서 사용 가능한 CLI 도구 (forge, cast, anvil, chisel)에 접근할 수 있습니다. 다음 단계로 foundry 프로젝트를 설정해봅시다:

**1 단계**: 새 프로젝트를 시작하려면 아래 명령어를 실행하세요:

```bash
forge init foundry_example 
```

**2 단계**: 프로젝트 폴더로 이동하세요.

```bash
cd foundry_example
ls   
```

Foundry 프로젝트를 초기화한 후, 현재 디렉토리에는 아래 내용이 포함되어야 합니다:

* **src**: 스마트 컨트랙트를 위한 기본 디렉토리입니다.
* **tests**: 테스트를 위한 기본 디렉토리입니다.
* **foundry.toml**: 기본 프로젝트 구성 파일입니다.
* **lib**: 프로젝트 종속성을 위한 기본 디렉토리입니다.
* **script**: Solidity 스크립팅 파일을 위한 기본 디렉토리입니다.

## 스마트 컨트랙트의 예시

이번 장에서는 초기화된 Foundry 프로젝트에서 샘플 카운터 컨트랙트를 사용할 것입니다. `src/` 폴더 안의 `counter.sol` 파일은 다음과 같아야 합니다:

```solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
contract Counter {
    uint256 public number;
    function setNumber(uint256 newNumber) public {
        number = newNumber;
    }
    function increment() public {
        number++;
    }
}
```

**코드 설명**

이것이 여러분이 작성한 스마트 컨트랙트입니다. **1행**은 솔리디티 버전 0.8.13 이상을 사용함을 보여줍니다. **4행에서 12행**까지, `Counter`라는 스마트 컨트랙트가 생성됩니다. 이 컨트랙트는 단순히 **setNumber** 함수를 사용하여 새 숫자를 저장하고, **increment** 함수를 호출하여 그 숫자를 증가시킵니다.

## Testing smart contract

Foundry는 다른 스마트 컨트랙트 개발 프레임워크에서 자바스크립트로 테스트를 작성하는 것과 달리, 솔리디티로 테스트를 작성할 수 있게 해줍니다. 우리가 초기화한 Foundry 프로젝트에서, `test/Counter.t.sol`은 솔리디티로 작성된 테스트의 예시입니다. 코드는 다음과 같습니다:

```solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import "forge-std/Test.sol";
import "../src/Counter.sol";
contract CounterTest is Test {
    Counter public counter;
    function setUp() public {
        counter = new Counter();
        counter.setNumber(0);
    }
    function testIncrement() public {
        counter.increment();
        assertEq(counter.number(), 1);
    }
    function testSetNumber(uint256 x) public {
        counter.setNumber(x);
        assertEq(counter.number(), x);
    }
}
```

위의 코드는 forge의 표준 라이브러리와 Counter.sol을 가져왔음을 보여줍니다.

위의 테스트들은 아래 내용을 확인합니다:

* 숫자가 증가하고 있나요?
* 숫자가 설정된 숫자와 같나요?

테스트가 잘 작동하는지 확인하려면 다음 명령어를 실행하세요:

```bash
forge test
```

**Output**

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-cb9cc1e4a12856ca617121cfeffb8c24ac4c4dbe%2Fforge-test.png?alt=media)

테스트 작성, 고급 테스팅 및 기타 기능에 대해 자세히 알고 싶다면, [Foundry의 문서](https://book.getfoundry.sh/forge/tests)를 참조하세요.

## 스마트 컨트랙트 컨트랙트 컴파일하기

아래 명령어를 통해 여러분의 컨트랙트를 컴파일하세요:

```bash
forge build 
```

## 스마트 컨트랙트 배포하기

Foundry를 사용하여 컨트랙트를 배포하려면, 계약을 배포할 계정의 RPC URL과 개인 키를 제공해야 합니다. Klaytn의 [rpc-provider](https://docs.klaytn.foundation/content/dapp/json-rpc/public-en) 목록을 확인하여 rpc-url을 찾고, [MetaMask](https://docs.klaytn.foundation/dapp/tutorials/connecting-metamask#install-metamask)를 사용하여 계정을 생성하세요.

**1단계**: Klaytn Baobab 네트워크에 계약을 배포하려면 아래의 명령어를 실행하세요:

```bash
$ forge create --rpc-url <your_rpc_url> --private-key <your_private_key> src/Counter.sol:Counter
```

**예시**

```bash
forge create --rpc-url https://klaytn-baobab-rpc.allthatnode.com:8551/qtKkeUE8ZEPI2cs0OHloJ6seI4Wfy36N --private-key hhdhdhdhprivatekeyhdhdhdhud src/Counter.sol:Counter
```

**주의 사항: private key 인수를 MetaMask에서의 귀하의 개인 키로 교체하세요. 개인 키를 노출하지 않도록 매우 주의하세요.**

**Output**

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-46df034a9e9674dc6ecec3e56febbf57dad7556d%2Ffoundry-create.png?alt=media)

**2단계**: 카운터 컨트랙트가 성공적으로 배포되었는지 확인하기 위해 [Klaytnscope](https://baobab.scope.klaytn.com/tx/0x669e39c9661fdab59aa34989b58b3f89376a93f846a0c71d2858918f58a307e2?tabId=internalTx)를 엽니다.

**3단계**: 검색 필드에 트랜잭션 해시를 복사하여 붙여넣고 Enter 키를 누릅니다. 정상적으로 작동했다면, 최근에 배포된 계약을 볼 수 있어야 합니다.

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-846e2d6d55031fc30a4e4bf81e195358b2c3d74f%2Fforge-scope.png?alt=media)

## 컨트랙트와 상호작용

스마트 컨트랙트를 성공적으로 배포한 후에는 함수를 호출하고 실행하길 원하게 될 것입니다. Klaytn Baobab 네트워크에서 배포된 컨트랙트와 상호 작용해 보겠습니다. [Cast](https://book.getfoundry.sh/reference/cast/cast-send.html)를 사용하면 됩니다. 이번 장에서는 `read-only` 함수를 실행하기 위해 [cast call](https://book.getfoundry.sh/reference/cast/cast-call)을 사용하는 방법과 `write` 함수를 실행하기 위해 [cast send](https://book.getfoundry.sh/reference/cast/cast-send)를 사용하는 방법을 배우게 될 것입니다.

**1. cast call**: 계약에 저장된 숫자를 가져오려면 `number` 함수를 호출해야 합니다. 실제로 작동하는 것을 보시려면, 아래의 명령어를 실행하세요.

```bash
cast call YOUR_CONTRACT_ADDRESS "number()" --rpc-url RPC-API-ENDPOINT-HERE
```

**예시**

```bash
cast call 0xe4d576c447733da7ca9197e88d34a74c3c865cff "number()" --rpc-url https://klaytn-baobab-rpc.allthatnode.com:8551/qtKkeUE8ZEPI2cs0OHloJ6seI4Wfy36N
```

**Output**

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-296dbb0ce806a95b6df0c87a5b914250df3cc967%2Fcast-call-number.png?alt=media)

데이터를 16진수 형식으로 받아야 합니다:

```bash
0x0000000000000000000000000000000000000000000000000000000000000000
```

그러나 원하는 결과를 얻으려면 위의 결과를 변환하기 위해 cast를 사용하세요. 이 경우, 데이터는 숫자이므로 이를 10진수로 변환하여 결과 0을 얻을 수 있습니다:

```bash
cast --to-base 0x0000000000000000000000000000000000000000000000000000000000000000 10
```

**Output**

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-e2fe2c00284b8b4f4fa4b5994f173206f39787ac%2Fcast-call-0.png?alt=media)

**2. cast send**: 카운터 컨트랙트에서 `setNumber` 함수와 같은 트랜잭션을 실행하여 서명하고 발행하려면 아래의 명령어를 실행하세요:

```bash
cast send --rpc-url=<RPC-URL> <CONTRACT-ADDRESS> “setNumber(uint256)” arg --private-key=<PRIVATE-KEY>
```

**예시**

```bash
cast send --rpc-url=https://klaytn-baobab-rpc.allthatnode.com:8551/qtKkeUE8ZEPI2cs0OHloJ6seI4Wfy36N  0xe4d576c447733da7ca9197e88d34a74c3c865cff "setNumber(uint256)"  10 --private-key=<private key>
```

**Output**

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-f4d66bf7181905633b7977f13b90ee8c4103ae76%2Fcast-send-setNum.png?alt=media)

**번호 교차 확인**

```bash
cast call 0xe4d576c447733da7ca9197e88d34a74c3c865cff "number()" --rpc-url https://klaytn-baobab-rpc.allthatnode.com:8551/qtKkeUE8ZEPI2cs0OHloJ6seI4Wfy36N
```

**Output**

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-745c97221169ce1038b373f87ce401987cdac1ad%2Fcast-call-10.png?alt=media)

이 데이터를 16진수 형식으로 받아야 합니다:

```bash
0x000000000000000000000000000000000000000000000000000000000000000a
```

원하는 결과를 얻으려면 위의 결과를 변환하기 위해 cast를 사용해야합니다. 이 경우, 데이터는 숫자이므로 이를 10진수로 변환하여 결과 10을 얻을 수 있습니다:

```bash
cast --to-base 0x000000000000000000000000000000000000000000000000000000000000000a 10
```

**Output**

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-a8536dd3f211050eadab4851b3b35a8b816cf45d%2Fcast-call-result-10.png?alt=media)

## Cast와 Anvil로 메인넷 포크하기

Foundry는 메인넷을 로컬 개발 네트워크 ([Anvil](https://book.getfoundry.sh/reference/anvil/)) 로 포크할 수 있게 해줍니다. 또한, [Cast](https://book.getfoundry.sh/reference/cast/)를 사용하여 실제 네트워크에서 컨트랙트와 상호 작용하고 테스트할 수 있습니다.

### 시작하기

이제 Foundry 프로젝트를 성공적으로 시작했으니, 아래의 명령어를 실행하여 메인넷(Cypress) 을 포크할 수 있습니다:

```bash
anvil --fork-url rpc-url
```

**예시**

```bash
anvil --fork-url https://archive-en.cypress.klaytn.net
```

**Output**

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-6c4d7f69183a9d6e21c8b6ff44708cbab68cac60%2Fanvil-localnode.png?alt=media)

이 명령어를 성공적으로 실행한 후, 당신의 터미널은 위의 이미지와 같이 보일 것입니다. 당신은 10개의 계정이 생성되고, 각각의 공개키와 개인키가 있으며, 또한 10,000개의 선불 토큰이 있을 것입니다. 포크된 체인의 RPC 서버는 `127.0.0.1:8545`에서 수신하고 있습니다.

네트워크를 포크한 것을 확인하기 위해, 최신 블록 번호를 요청할 수 있습니다:

```bash
curl --data '{"method":"eth_blockNumber","params":[],"id":1,"jsonrpc":"2.0"}' -H "Content-Type: application/json" -X POST localhost:8545 
```

위의 작업에서 얻은 결과를 [16진수에서 10진수](https://www.rapidtables.com/convert/number/hex-to-decimal.html)로 변환할 수 있습니다. 네트워크를 포크한 시점의 최신 블록 번호를 얻어야 합니다. 이를 검증하려면 [Klaytnscope](https://klaytnscope.com/block/118704896?tabId=txList)에서 블록 번호를 참조하여 대조하십시오.

### Illustration

이번 장에서는 oUSDC를 보유한 사람으로부터 Anvil에 의해 생성된 계정(0x70997970C51812dc3A010C7d01b50e0d17dc79C8 - Bob) 으로 oUSDC 토큰을 전송하는 방법을 배울 예정입니다.

**oUSDC 전송하기**

Klaytnscope로 가서 oUSDC 토큰의 보유자를 검색하세요 (여기). 무작위 계정을 선택합니다. 이 예시에서는 `0x8e61241e0525bd45cfc43dd7ba0229b422545bca`를 사용하게 됩니다.

컨트랙트와 계정을 환경 변수로 내보냅시다:

```bash
export BOB=0x70997970C51812dc3A010C7d01b50e0d17dc79C8
export oUSDC=0x754288077d0ff82af7a5317c7cb8c444d421d103
export oUSDCHolder=0x8e61241e0525bd45cfc43dd7ba0229b422545bca
```

Bob의 잔액을 cast 호출을 사용하여 확인할 수 있습니다:

```bash
cast call $oUSDC \
  "balanceOf(address)(uint256)" \
  $BOB
```

**Output**

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-576176e017f9a9767c6815a2fe6851ac11bc6039%2FoUsdcBob4.png?alt=media)

마찬가지로, cast 호출을 사용하여 oUSDC 보유자의 잔액도 확인할 수 있습니다:

```bash
cast call $oUSDC \
  "balanceOf(address)(uint256)" \
  $oUSDCHolder
```

**Output**

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-2459ed1a1b0be5f2af76a53ed53e89b0bc781670%2FoUsdcHolder4.png?alt=media)

cast send를 사용하여 운좋은 사용자로부터 앨리스에게 일부 토큰을 전송해봅시다:

```bash
cast rpc anvil_impersonateAccount $oUSDCHolder
cast send $oUSDC \
--from $oUSDCHolder\
  "transfer(address,uint256)(bool)" \
  $BOB \
 1000000
```

**Output**

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-2c417148c352dfb314a8388071a3cfc28a36d7fc%2Fcast-send.png?alt=media)

전송이 제대로 작동했는지 확인해봅시다:

```bash
cast call $oUSDC \
  "balanceOf(address)(uint256)" \
  $BOB
```

**Output**

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-013c85be71d0bd877ce6569dd1b994d5a12d13a5%2FoUsdcBobAfter.png?alt=media)

```bash
cast call $oUSDC \
  "balanceOf(address)(uint256)" \
  $oUSDCHolder
```

**Output**

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-421dae393d36319d60293caf75affb3fb7da5fcc%2FoUsdcHolderAfter.png?alt=media)

더 깊이 있는 가이드를 원하시면, [Foundry 문서](https://book.getfoundry.sh/)를 참조해주세요. 또한, 이 가이드에 대한 코드의 자세한 내용은 [GitHub](https://github.com/klaytn/examples/tree/main/foundry)에서 찾을 수 있습니다.


# Deploying Smart Contract Using Hardhat

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-34b5f2b1d4ebee0cce997f31871095ee02717681%2FKlaytn-hardhat.png?alt=media)

## 소개

이번 장에서는 [Hardhat](https://hardhat.org/)을 사용하여 Klaytn Baobab 네트워크에 Soulbound 토큰을 배포하는 과정을 안내해 드리겠습니다.

Hardhat은 다음을 도와줄 스마트 컨트랙트 개발 환경입니다:

* 스마트 컨트랙트를 개발하고 컴파일합니다.
* 스마트 컨트랙트와 dApps를 디버그, 테스트, 배포합니다.

Soul-bound 토큰(SBTs) 은 전송할 수 없는 NFTs(비대체 가능 토큰) 입니다. 즉, 한 번 획득하면 다른 사용자에게 팔거나 전송할 수 없습니다. SBT에 대해 더 자세히 알고 싶으시면, 어떻게 작동하는지 및 사용 사례에 대해 Vitalik Buterin이 발표한 이 [참고 문서](https://vitalik.ca/general/2022/01/26/soulbound.html)를 확인하실 수 있습니다.

이 가이드를 마치면 다음을 수행할 수 있게 됩니다:

* Klaytn에서 Harthat 프로젝트 설정.
* 간단한 Soul-bound 토큰 생성.
* Hardhat을 사용하여 스마트 컨트랙트 컴파일.
* Hardhat을 사용하여 스마트 컨트랙트 테스트, 배포 및 상호 작용.
* Hardhat의 포크 기능 탐색.

## 사전 요구 사항

이 튜토리얼을 따르려면 아래 조건이 필요합니다:

* 코드 에디터: VS-Code와 같은 소스 [코드 에디터](https://code.visualstudio.com/download).
* [Metamask](https://docs.klaytn.foundation/dapp/tutorials/connecting-metamask#install-metamask): 컨트랙트를 배포하고, 트랜잭션에 서명하고, 컨트랙트와 상호 작용하는 데 사용됩니다.
* RPC Endpoint: 지원되는 [Endpoint Providers](https://docs.klaytn.foundation/content/dapp/json-rpc/public-en) 중 하나에서 이를 얻을 수 있습니다.
* [Faucet](https://baobab.wallet.klaytn.foundation/faucet)에서 테스트 KLAY: 충분한 KLAY로 계정을 충전합니다.
* [NodeJS 및 NPM](https://nodejs.org/en/)

## 개발 환경 설정

Hardhat을 사용하기 위해서는 개발 환경을 설정하고 Hardhat을 설치해야 합니다. 다음 단계로 이 작업을 수행해봅시다:

**1 단계**: 프로젝트 디렉토리 생성

```bash
mkdir soulbound-tokens
cd soulbound-tokens
```

**2 단계**: npm 프로젝트 초기화

터미널에 다음 명령어를 붙여넣어 package.json 파일을 생성하세요.

```bash
npm init -y
```

**3 단계**: Hardhat과 기타 종속성 설치:

* Hardhat을 설치하려면 아래의 코드를 터미널에 붙여넣으세요.

```bash
npm install --save-dev hardhat
```

* 다른 의존성을 설치하려면 아래 코드를 터미널에 붙여넣으세요.

```bash
npm install dotenv @nomicfoundation/hardhat-toolbox @klaytn/contracts
```

> 참고: 이것은 이 프로젝트에 필요한 다른 의존성을 설치합니다. `hardhat`, `hardhat-toolbox`, `klaytn/contract`, `dotenv` 등이 포함됩니다.

**4 단계**: Hardhat 프로젝트 초기화:

아래 명령어를 실행하여 Hardhat 프로젝트를 시작하세요.

```bash
npx hardhat
```

이 가이드에서는 아래와 같이 typescript 프로젝트를 선택하게 될 것입니다:

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-639e9625430552e7e9fdd19f5db6c51bc9fe0016%2Fhardhat-init.png?alt=media)

Hardhat프로젝트를 초기화한 후 현재 디렉토리에는 다음과 같은 내용이 포함되어야 합니다:

**contracts/** – 이 폴더에는 스마트 컨트랙트 코드가 포함되어 있습니다.

**scripts/** – 이 폴더에는 블록체인 네트워크에 컨트랙트를 배포하는 코드가 포함되어 있습니다.

**test/** – 이 폴더에는 스마트 컨트랙트를 테스트하는 모든 유닛 테스트가 포함되어 있습니다.

**hardhat.config.ts** – 이 파일에는 Hardhat의 작동과 소울 바운드 토큰의 배포에 중요한 환경 설정이 포함되어 있습니다.

**5 단계**: .env 파일을 생성합니다.

이제 프로젝트 폴더에 .env 파일을 생성하세요. 이 파일은 .env 파일에서 process.env로 환경 변수를 로드하는 데 도움이 됩니다.

* 터미널에 다음 명령어를 붙여넣어 .env 파일을 생성하세요.

```bash
touch .env
```

* 파일을 생성한 후, .env 파일을 다음과 같이 구성합시다:

```js
 KLAYTN_BAOBAB_URL= "Your Baobab RPC link"
 PRIVATE_KEY= "your private key copied from MetaMask wallet"
```

**6 단계**: Hardhat 설정하기

다음과 같은 환경 설정으로 `hardhat.config.ts` 파일을 수정하세요:

```js
require("@nomicfoundation/hardhat-toolbox");
require('dotenv').config()


module.exports = {
  solidity: "0.8.17",
  networks: {
    baobab: {
      url: process.env.KLAYTN_BAOBAB_URL || "",
      gasPrice: 250000000000,
      accounts:
        process.env.PRIVATE_KEY !== undefined ? [process.env.PRIVATE_KEY] : [],
    }
  }
};

```

이제 개발 환경이 모두 설정되었으므로, 소울 바운드 토큰 스마트 컨트랙트를 작성해봅시다.

## SBT 스마트 컨트랙트 생성

이번 장에서는 커뮤니티에서 검증된 코드의 견고한 기반 위에 구축된 안전한 스마트 컨트랙트 개발을 위한 라이브러리인 [Klaytn 컨트랙트](https://github.com/klaytn/klaytn-contracts)를 사용하게 됩니다. Klaytn 컨트랙트는 오픈 제플린 컨트랙트으로부터 포크한 라이브러이입니다.

> 참고: `개발 환경 설정` 장의 **3 단계**에서 이미 이 라이브러리를 설치했습니다.

**1 단계**: 탐색기 창에서 contracts 폴더를 선택하고, 새 파일 버튼을 클릭하여 `SBT.sol`이라는 새 파일을 생성합니다.

**2 단계**: 파일을 열고 아래의 코드를 붙여넣습니다:

```js
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

import "@klaytn/contracts/KIP/token/KIP17/KIP17.sol";
import "@klaytn/contracts/utils/Counters.sol";
import "@klaytn/contracts/access/Ownable.sol";

contract SoulBoundToken is KIP17, Ownable {
    using Counters for Counters.Counter;

    Counters.Counter private _tokenIdCounter;

    constructor() KIP17("SoulBoundToken", "SBT") {}

    function safeMint(address to) public onlyOwner {
        uint256 tokenId = _tokenIdCounter.current();
        _tokenIdCounter.increment();
        _safeMint(to, tokenId);
    }


    function _beforeTokenTransfer(address from, address to, uint256) pure override internal {
        require(from == address(0) || to == address(0), "This a Soulbound token. It cannot be transferred.");
    }

    function _burn(uint256 tokenId) internal override(KIP17) {
        super._burn(tokenId);
    }
}
```

**Code Walkthrough**

This is your smart contract. **line 1** shows that Hardhat uses the Solidity version 0.8.7 or greater. Other than that, it imports KIP17.sol and other supporting contracts. From **lines 6-12**, a smart contract that inherits KIP17 is been created. Also, the token name and symbol was passed in the constructor.

As you can see in the code above, the token name and symbol have been set to **SoulBoundToken** and **SBT** respectively. You can change the token name and symbol to anything you desire.

One major thing in this contract is that it prohibits token transfer, which makes the issued tokens soulbond.

## Testing SBT Smart Contract

In this section, we would be testing some of our contract functionalities.

**Step 1**: In the Explorer pane, select the test folder and click the New File button to create a new file named `sbtTest.ts`

**Step 2**: Copy the code below in the `sbtTest.ts` file.

```js
// This is an example test file. Hardhat will run every *.ts file in `test/`,
// so feel free to add new ones.

// Hardhat tests are normally written with Mocha and Chai.

// We import Chai to use its asserting functions here.
const { expect } = require("chai");

// We use `loadFixture` to share common setups (or fixtures) between tests.
// Using this simplifies your tests and makes them run faster, by taking
// advantage of Hardhat Network's snapshot functionality.
const { loadFixture } = require("@nomicfoundation/hardhat-network-helpers");

// `describe` is a Mocha function that allows you to organize your tests.
// Having your tests organized makes debugging them easier. All Mocha
// functions are available in the global scope.
//
// `describe` receives the name of a section of your test suite, and a
// callback. The callback must define the tests of that section. This callback
// can't be an async function.
describe("Token contract", function () {
  // We define a fixture to reuse the same setup in every test. We use
  // loadFixture to run this setup once, snapshot that state, and reset Hardhat
  // Network to that snapshot in every test.
  async function deployTokenFixture() {
    // Get the ContractFactory and Signers here.
    const sbt = await ethers.getContractFactory("SoulBoundToken");
    const [owner, addr1, addr2] = await ethers.getSigners();

    // To deploy our contract, we just have to call Token.deploy() and await
    // its deployed() method, which happens onces its transaction has been
    // mined.
    const sbtContract = await sbt.deploy();

    await sbtContract.deployed();

    // Fixtures can return anything you consider useful for your tests
    return { sbtContract, owner, addr1, addr2 };
  }

  // You can nest describe calls to create subsections.
  describe("Deployment", function () {
    // `it` is another Mocha function. This is the one you use to define each
    // of your tests. It receives the test name, and a callback function.
    //
    // If the callback function is async, Mocha will `await` it.
    it("Should mint SBT to owner", async function () {
      const { sbtContract, owner } = await loadFixture(deployTokenFixture);
      const safemint = await sbtContract.safeMint(owner.address);
      expect(await sbtContract.ownerOf(0)).to.equal(owner.address);
    });
  });

  describe("Transactions", function () {
    it("Should prohibit token transfer using transferFrom", async function () {
      const { sbtContract, owner, addr1 } = await loadFixture(
        deployTokenFixture
      );

      const safemintTx = await sbtContract.safeMint(owner.address);

      // prohibit token transfer of token id (0) from owner to addr1
      await expect(
        sbtContract.transferFrom(owner.address, addr1.address, 0)
      ).to.be.reverted;
  });

  it("Should prohibit token transfer using safeTransferFrom", async function () {
    const { sbtContract, owner, addr1 } = await loadFixture(
      deployTokenFixture
    );

    const safemintTx = await sbtContract.safeMint(owner.address);

    // prohibit token transfer of token id (0) from owner to addr1
    await expect(sbtContract['safeTransferFrom(address,address,uint256)'](
      owner.address,
      addr1.address,
      0 
  )).to.be.reverted;
});


});

})
```

In the code you just copied, line 7 & 12 shows you imported expect from [Chai](https://www.chaijs.com/api/bdd/) and [loadFixture](https://hardhat.org/tutorial/testing-contracts#reusing-common-test-setups-with-fixtures) from hardhat-network-helpers.

The tests above check the following:

* Is the owner of a particular token id the same as who it was minted to?
* Did it prohibit transfer of tokens between accounts?

**Step 3**: To run your test, run the command below:

```bash
npx hardhat test test/sbtTest.ts 
```

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-5431dfa654670f840d2821303f2e3d8b828708f9%2FsbtTest.png?alt=media)

For more in-depth guide on testing, please check [Hardhat testing](https://hardhat.org/hardhat-runner/docs/guides/test-contracts).

## Deploying the smart contract

Scripts are JavaScript/Typescript files that help you deploy contracts to the blockchain network. In this section, you will create a script for the smart contract.

**Step 1**: In the Explorer pane, select the “scripts” folder and click the New File button to create a new file named `sbtDeploy.ts`.

**Step 2**: Copy and paste the following code inside the file.

> Note: input your MetaMask wallet address in the `deployerAddr` variable.

```js
import { ethers } from "hardhat";

async function main() {

    const deployerAddr = "Your Metamask wallet address";
    const deployer = await ethers.getSigner(deployerAddr);

    console.log(`Deploying contracts with the account: ${deployer.address}`);
    console.log(`Account balance: ${(await deployer.getBalance()).toString()}`);

  const sbt = await ethers.getContractFactory("SoulBoundToken");
  const sbtContract = await sbt.deploy();


  await sbtContract.deployed();

console.log(`Congratulations! You have just successfully deployed your soul bound tokens.`);
console.log(`SBT contract address is ${sbtContract.address}. You can verify on https://baobab.scope.klaytn.com/account/${sbtContract.address}`);
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});
```

**Step 3**: In the terminal, run the following command which tells Hardhat to deploy your SBT token on the Klaytn Test Network (Baobab)

```bash
npx hardhat run scripts/sbtDeploy.ts --network baobab
```

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-c125e1d650a2019e8a84cdf413897c1902b3143c%2FsbtDeploy.png?alt=media)

**Step 4**: Open [Klaytnscope](https://baobab.scope.klaytn.com/) to check if the SBT token has been deployed successfully.

**Step 5**: Copy and paste the deployed contract address in the search field and press Enter. You should see the recently deployed contract.

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-4982c34f150e001e0f493172920ca19bbae280b9%2FsbtKS.png?alt=media)

## Hardhat Forking

Hardhat provides developers the functionality of simulating the mainnet (at any given block) to a local development network. One of the major benefit of this feature is that it enables developers to interact with deployed contract and also write test for complex cases.

For this feature to work effectively, you need to connect to an archive node. You can read more about this feature [here](https://hardhat.org/hardhat-network/docs/guides/forking-other-networks#forking-other-networks)

### Forking Mainnet

Now that we have our Hardhat project set up let’s fork the Klaytn Mainnet using Hardhat. Open your terminal and run this command

```bash
npx hardhat node --fork <YOUR ARCHIVE NODE URL>

npx hardhat node --fork https://archive-en.cypress.klaytn.net
```

You can also configure `hardhat.config.ts` - Hardhat Network to always do this:

```
networks: {
  hardhat: {
    forking: {
      url: "<YOUR ARCHIVE NODE URL>",
    }
  }
}
```

**Output**

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-424e93366f328f740723314648f0c7aea226b97f%2Fhardhat-fork.png?alt=media)

After successfully running this command, your terminal looks like the above image. You'll have 20 development accounts that are pre-funded with 10,000 test tokens.

The forked chain's RPC server is listening at `http://127.0.0.1:8545/`. You can verify the forked network by querying the latest block number. Let's try to make a cURL to the RPC to get the block number. Open a new terminal window and use the following command:

```bash
curl --data '{"method":"eth_blockNumber","params":[],"id":1,"jsonrpc":"2.0"}' -H "Content-Type: application/json" -X POST localhost:8545 
```

**Output**

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-c70f374cd99ecf386a0e3faa4a8388f9b14dec36%2Fhardhat-fork-bn.png?alt=media)

The output is an hexadecimal as seen above. To get the block number from the hex, convert the hex to a decimal using this [tool](https://www.rapidtables.com/convert/number/hex-to-decimal.html). You should get the latest block number from the time you forked the network. You can confirm the block number on [klaytnscope](https://scope.klaytn.com/).

### Forking at a Block

With hardhat, you can fork the mainnet at a particular block. In that case, let’s fork the chain at block number `105701850`.

```bash
npx hardhat node --fork <YOUR ARCHIVE NODE URL> --fork-block-number 105701850

npx hardhat node --fork https://archive-en.cypress.klaytn.net --fork-block-number 105701850
```

To confirm the forked chain at the stated block, open a new terminal window and use the following command:

```bash
curl --data '{"method":"eth_blockNumber","params":[],"id":1,"jsonrpc":"2.0"}' -H "Content-Type: application/json" -X POST localhost:8545 
```

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-3f1f796ea1af294d45b6f224c2561451cb6e29d5%2Fhardhat-fork-bnII.png?alt=media)

The output returns hexadecimal which when converted using this [tool](https://www.rapidtables.com/convert/number/hex-to-decimal.html) should be equal to `105701850`.

For more in-depth guide on Hardhat, please refer to [Hardhat Docs](https://hardhat.org/hardhat-runner/docs/getting-started). Also, you can find the full implementation of the code for this guide on [GitHub](https://github.com/klaytn/examples/tree/main/hardhat/soulbound-tokens)


# Deploying Smart Contract Using KEN

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-bd7114144146f6af42a03d41c7e9edb5e526cc62%2FklaytnXken.png?alt=media)

Before you start, let's get familiar with several Klaytn-specific terms.

* **엔드포인트 노드 (EN)**: Klaytn 네트워크에 대한 JSON-RPC API 요청을 처리하는 노드입니다. 엔드포인트 노드는 합의에 참여하지 않습니다.
* **KLAY**: Klaytn 네이티브(native) 코인.
* **caver-js**: Klaytn JSON-RPC API의 자바스크립트 구현체
* **Baobab**: Klaytn 테스트넷
* **Cypress**: Klaytn 메인넷

This step by step guide will walk you through the process of launching an Endpoint Node (EN) of Baobab testnet and building a basic smart contract with your new account. The tutorial consists of two parts, setting up an EN and deploying a smart contract through your EN.

> 스마트 컨트랙트를 배포하고 트랜잭션을 제출하려면 트랜잭션 수수료로 KLAY가 필요하기 때문에, 이 가이드는 **Baobab** 테스트넷을 사용합니다. For the development purpose, testnet KLAY can be obtained from the [Baobab faucet](https://baobab.wallet.klaytn.foundation/faucet).

## 1. 엔드포인트 노드를 시작하고 계정에 Baobab 테스트넷 KLAY 받기 (Linux, Mac) <a href="#id-1-launch-an-endpoint-node-and-add-baobab-testnet-klay-to-your-account-linux-mac" id="id-1-launch-an-endpoint-node-and-add-baobab-testnet-klay-to-your-account-linux-mac"></a>

The first part of this tutorial explains how to launch an EN, create a new account, and top up your account with the faucet in the Baobab Klaytn Wallet.

* [Launch an Endpoint Node](/content/getting-started/quick-start/launch-an-en)
* [Top up your Account](/content/getting-started/quick-start/top-up-your-account)

## 2. 스마트 컨트랙트 배포: KlaytnGreeter <a href="#id-2-deploying-a-smart-contract-klaytngreeter" id="id-2-deploying-a-smart-contract-klaytngreeter"></a>

The second of this guide shows how to create smart contracts and deploy them on the Klaytn Baobab network. Before getting into developing smart contracts, you need to set up the development tools, install caver-js and Truffle.

* [Install Development Tools](/content/getting-started/quick-start/install-development-tools)
* [Deploy a Smart Contract](/content/getting-started/quick-start/deploy-a-smart-contract)
* [Check the Deployment](/content/getting-started/quick-start/check-the-deployment)


# Launch an Endpoint Node

## Download and Initialize an Endpoint Node (EN) <a href="#download-and-initialize-an-endpoint-node-en" id="download-and-initialize-an-endpoint-node-en"></a>

Unzip the provided [ken binary package](/content/installation-guide/deployment/download#get-the-packages) and copy the files into the klaytn folder.\
**Note**: Please download appropriate package starting with `ken`.

Mac 사용자의 경우, 다음 명령으로 다운로드한 파일을 압축 해제합니다.

```bash
$ tar zxf ken-baobab-vX.X.X-X-darwin-amd64.tar.gz
$ export PATH=$PATH:$PWD/ken-darwin-amd64/bin
```

Linux 사용자의 경우, 다음 명령으로 다운로드한 파일을 압축 해제합니다.

```bash
$ tar zxf ken-baobab-vX.X.X-X-linux-amd64.tar.gz
$ export PATH=$PATH:$PWD/ken-linux-amd64/bin
```

블록체인 데이터를 저장할 데이터 디렉토리를 만들어야 합니다. 이 튜토리얼에서는 홈 디렉터리에 `kend_home` 폴더를 생성하겠습니다.

```bash
$ mkdir -p ~/kend_home
```

## EN 환경설정 <a href="#configuring-the-en" id="configuring-the-en"></a>

설정 파일인 `kend.conf`는 `ken-xxxxx-amd64/conf/`에 위치합니다. For the details of configurable parameters, you can refer to the [EN Configuration Guide](/content/operation-guide/configuration). Baobab 테스트넷의 EN을 실행하려면, 다음과 같이 `kend.conf` 파일을 업데이트하시기 바랍니다.

```
# cypress, baobab은 NETWORK_ID를 명시하지 않은 경우에만 사용할 수 있습니다.
NETWORK = "baobab"
# NETWORK_ID를 명시하면 개인(private) 네트워크가 생성됩니다.
NETWORK_ID=
...
RPC_API="klay,net" # 추후 truffle을 위해 net 모듈을 열어야 합니다.
...
DATA_DIR=~/kend_home
```

## EN 실행하기 <a href="#launching-the-en" id="launching-the-en"></a>

EN을 시작하려면 다음 명령을 실행합니다.

```bash
$ kend start
 Starting kend: OK
```

## EN 확인하기 <a href="#checking-the-en" id="checking-the-en"></a>

EN이 구동 중인지 확인하려면 다음 명령을 실행합니다.

```bash
$ kend status
kend is running
```

## EN의 로그 확인 <a href="#checking-the-log-of-the-en" id="checking-the-log-of-the-en"></a>

EN의 로그를 확인하려면 다음 명령을 실행합니다.

```bash
$ tail -f ~/kend_home/logs/kend.out
...
INFO[03/26,15:37:49 +09] [5] Imported new chain segment                blocks=1    txs=0  mgas=0.000  elapsed=2.135ms   mgasps=0.000    number=71340 hash=f15511…c571da cache=155.56kB
...
```

## 문제 해결 <a href="#troubleshooting" id="troubleshooting"></a>

Please refer to the [Troubleshooting](/content/operation-guide/errors-and-troubleshooting) if you have trouble in launching the Klaytn Endpoint Node.


# Top up your Account

## 콘솔에 연결하기 <a href="#attaching-to-the-console" id="attaching-to-the-console"></a>

Klaytn 엔드포인트 노드는 자바스크립트 콘솔과 함께 제공됩니다. 콘솔 명령행에서 EN을 향한 Klaytn API 호출 중 일부를 시작할 수 있습니다. 자바스크립트 콘솔에 연결하려면 다음 명령을 실행하세요.

```bash
$ ken attach ~/kend_home/klay.ipc
Welcome to the Klaytn JavaScript console

!instance: Klaytn/vX.X.X/XXXX-XXXX/goX.X.X
 datadir: ~/kend_home
 modules: admin:1.0 debug:1.0 governance:1.0 istanbul:1.0 klay:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0

 >
```

**참고**: 모든 블록을 다운로드 할 때까지 기다려야 합니다. 콘솔에 `klay.blockNumber`를 입력하고 [여기](https://baobab.scope.klaytn.com/)의 현재 블록 번호와 일치하는지 확인하세요.

**참고**: `klay` 또는 `personal`을 입력해 사용 가능한 함수 목록을 가져옵니다.

## 새로운 Klaytn 계정 생성 <a href="#creating-a-new-klaytn-account" id="creating-a-new-klaytn-account"></a>

자바스크립트 콘솔에서 새 Klaytn 계정을 생성하려면 다음 명령을 실행하세요. 개인키는 입력한 패스프레이즈로 암호화됩니다.

```javascript
> personal.newAccount()
Passphrase:  # 암호를 입력하세요
Repeat passphrase:
"0x75a59b94889a05c03c66c3c84e9d2f8308ca4abd" # 생성된 계정 주소
```

키스토어 파일은 `kend.conf`에서 설정한 `DATA_DIR`인 EN 데이터 디렉토리의 `keystore` 폴더 아래에 생성될 것입니다. 만일 빠른 시작 기본 가이드라인을 따를 경우, 이는`~/kend_home/keystore/`이어야 합니다.

```javascript
$ ls ~/kend_home/keystore/
UTC--2019-06-24T11-20-15.590879000Z--75a59b94889a05c03c66c3c84e9d2f8308ca4abd
```

## Klaytn 계정 잠금 해제 <a href="#unlocking-the-klaytn-account" id="unlocking-the-klaytn-account"></a>

생성된 계정을 잠금 해제하려면, 다음 명령을 실행합니다. 이는 300초 동안 계정을 잠금 해제합니다. **참고**: 잠금 해제 기간을 수동으로 설정하려면, 다음 [링크](/content/dapp/json-rpc/api-references/personal#personal_unlockaccount)를 참조하세요. **`경고`**: 계정 잠금 해제는 조심해서 하지 않으면 매우 위험할 수 있습니다. EN이 해커에 의해 해킹되면, 해커가 토큰을 빼앗을 가능성이 있습니다. To use safer method, refer to this [deployment guide using private key](/content/dapp/tutorials/count-dapp/6.-deploy-contract#deploy-method-1-by-private-key)

```javascript
> personal.unlockAccount('75a59b94889a05c03c66c3c84e9d2f8308ca4abd') # 잠금을 해제할 계정 주소
Unlock account 75a59b94889a05c03c66c3c84e9d2f8308ca4abd
Passphrase: # 암호를 입력하세요
true
```

## Baobab Faucet에서 테스트넷 KLAY 받기 <a href="#getting-testnet-klay-from-the-baobab-faucet" id="getting-testnet-klay-from-the-baobab-faucet"></a>

* KlaytnWallet의 Baobab Faucet 사용하기
* Access [https://baobab.wallet.klaytn.foundation](https://baobab.wallet.klaytn.foundation/).
* 지갑에 로그인하기 위하여 지갑에서 새 계정을 만들거나 위의 EN 자바스크립트 콘솔에서 생성한 키스토어 파일을 사용할 수 있습니다.
* 왼쪽 창 메뉴에서 "KLAY Faucet"으로 이동하고, "Run Faucet" 버튼을 클릭해 150 KLAY를 얻습니다.

  KLAY Faucet를 24시간마다 한 번씩 실행할 수 있습니다.
* KLAY를 얻기 위해 새 계정을 만들었다면 EN의 생성된 계정으로 KLAY 보냅니다.

## 계정 잔액 확인 <a href="#checking-the-balance-in-your-account" id="checking-the-balance-in-your-account"></a>

계정의 잔액을 확인하려면, 다음 명령을 실행합니다.

기본 단위는 peb (1 KLAY = 10 ^ 18 peb)입니다. KLAY 단위에 대한 자세한 내용은 [KLAY의 단위](/content/klaytn/design/klaytn-native-coin-klay#units-of-klay)에서 확인할 수 있습니다.

```javascript
> klay.getBalance('75a59b94889a05c03c66c3c84e9d2f8308ca4abd') # 계정 주소를 입력하세요
1e+21  # 1000 KLAY
```

## 콘솔 종료 <a href="#exiting-the-console" id="exiting-the-console"></a>

자바스크립트 콘솔을 떠나려면, 다음 명령을 실행하세요.

```javascript
> exit
$
```


# Install Development Tools

## caver-js 설치 <a href="#installing-caver-js" id="installing-caver-js"></a>

다음과 같은 klaytn 프로젝트 디렉토리를 만드는 것이 좋습니다:

```bash
$ mkdir $HOME/klaytn
```

> 계속 진행하기 위해 `npm`과 `node.js` 설치가 요구됩니다. 시스템에 설치하기 위해 [get-npm](https://www.npmjs.com/get-npm)과 [node.js](https://nodejs.org/en/)를 참조해 주시길 바랍니다.

​[caver-js](/content/dapp/sdk/caver-js)는 Klaytn 네트워크를 위한JSON RPC 프레임워크입니다(이더리움 네트워크의 web3.js와 동일). caver-js를 설치하기 전에, `npm init`을 통해 `package.json`을 생성해야 합니다. 이후 caver-js를 설치하기 위해 `npm install caver-js`를 입력하세요.

```bash
$ npm init # klaytn 프로젝트 디렉토리에서 npm 초기화
$ npm install caver-js
```

**참고**: caver-js를 이미 설치한 경우, 최신 버전으로 업데이트하시길 바랍니다.

```bash
$ npm cache clean --force # npm 캐시 초기화
$ npm install caver-js@latest # caver-js를 최신 버전으로 업데이트
```

caver-js를 업데이트하는 동안 다음 오류가 발생하면, `websocket` 디렉토리의 `.git` 폴더를 제거하세요.

```bash
npm ERR! path /Users/username/klaytn/node_modules/websocket
npm ERR! code EISGIT
npm ERR! git /Users/username/klaytn/node_modules/websocket: Appears to be a git repo or submodule.
npm ERR! git     /Users/username/klaytn/node_modules/websocket
npm ERR! git Refusing to remove it. Update manually,
npm ERR! git or move it out of the way first.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/username/.npm/_logs/2019-06-25T01_49_37_032Z-debug.log​

$ rm /Users/username/klaytn/node_modules/websocket/.git
```

**참고**: web3.js의 `web3.eth...`로 시작하는 모든 함수 호출은 `caver.klay...`로 대체되어야 합니다.

`web3.eth.sendTransaction({ ... })` (X)

`caver.klay.sendTransaction({ ... })` (O)

## 트러플 설치 <a href="#installing-truffle" id="installing-truffle"></a>

이 튜토리얼에서 트러플은 솔리디티로 작성된 스마트 컨트랙트를 컴파일하고 배포하는 데 사용됩니다. 현재 Klaytn은 트러플 버전 4.1.15를 지원합니다. 트러플에 대한 자세한 내용은 다음 사이트를 참조하세요:

* 트러플 스토리지 - <https://github.com/trufflesuite/truffle>​
* 트러플 문서 - <https://trufflesuite.com/docs>

트러플은 다음 방법들로 설치 가능합니다:

1\) 다음 명령을 실행하여 npm을 전역(global)으로 사용할 수 있습니다:

```bash
$ sudo npm install -g truffle@4.1.15
$ cd /usr/local/lib/node_modules/truffle
$ sudo npm install solc@0.5.6
$ cd -
```

또는

2\) 지역적(local)으로 사용할 수 있습니다. 즉, 로컬 디렉토리에서 다음을 실행합니다:

```bash
# $HOME/klaytn/에 있다고 가정합니다.
$ npm install truffle@4.1.15
$ cd node_modules/truffle
$ npm install solc@0.5.6
$ cd -
$ ln -s node_modules/truffle/build/cli.bundled.js truffle
$ export PATH=`pwd`:$PATH
```

## vvisp 설치 <a href="#installing-vvisp" id="installing-vvisp"></a>

vvisp은 스마트 컨트랙트 개발을 위해 [HEACHI LABS](https://henesis.io/)에서 제공하는 사용하기 쉬운 cli 도구/프레임워크입니다. 단일 명령만으로 환경을 쉽게 설정하고, Klaytn 스마트 컨트랙트를 배포 및 실행할 수 있습니다. 트러플 프레임워크를 지원하므로, 트러플에 익숙한 개발자는 어려움 없이 vvisp을 사용할 수 있습니다.

Here, we introduce how to install vvisp and use it to set up the Klaytn dApp development environment.

* vvisp 스토리지 - <https://github.com/HAECHI-LABS/vvisp>
* vvisp 문서 - <https://github.com/HAECHI-LABS/vvisp/blob/dev/README_KLAYTN.md>

npm 또는 yarn이 존재하는 경우 다음 명령을 실행하여 vvisp을 쉽게 설치할 수 있습니다:

```bash
$ npm install -g @haechi-labs/vvisp
# 또는 yarn을 사용하는 경우
$ yarn global add @haechi-labs/vvisp
```

설치 시 vvisp 명령을 사용하여 제대로 설치되었는지 확인할 수 있습니다. **참고**: **v2.1.0** 이상의 버전을 사용해야 합니다.

```bash
$ vvisp
Usage: vvisp <command> [options]

where <command> is one of: compile, console, deploy-contract, deploy-service, flatten, gen-script, init

Options:
  -v, --version  output the version number
  -h, --help     output usage information

Commands:

   compile [files...]                       compile the smart contracts

   console [script-api-path]                run interactive shell to execute contract scripts

   deploy-contract <file> [arguments...]    deploy the smart contracts

   deploy-service                           deploy or upgrade smart contract service using the deployment configure file

   flatten <files...>                       flatten the smart contracts

   gen-script [files...]                    generate javascript libraries communicating the smart contracts

   init [name]                              initialize directory to use vvisp

# 설치된 버전을 확인할 수 있습니다.
$ vvisp --version
v2.1.0
```


# Deploy a Smart Contract

이제 Klaytn 스마트 컨트랙트를 개발하고 배포할 준비가 되었습니다!

## 프로젝트 디렉토리 생성 <a href="#creating-a-project-directory" id="creating-a-project-directory"></a>

우선, 소스 코드가 위치할 디렉토리를 생성하세요.

```bash
$ mkdir klaytn-testboard
$ cd klaytn-testboard
```

## 트러플 초기화 <a href="#initializing-truffle" id="initializing-truffle"></a>

컨트랙트 배포를 위해 트러플을 초기화하세요.

```bash
$ truffle init
```

## 간단한 솔리디티 스마트 컨트랙트 작성 <a href="#writing-a-simple-smart-contract-in-solidity" id="writing-a-simple-smart-contract-in-solidity"></a>

`klaytn-testboard/contracts` 디렉토리에 `KlaytnGreeter.sol`를 생성합니다.

```bash
$ cd contracts
$ touch KlaytnGreeter.sol
$ vi KlaytnGreeter.sol
```

KlaytnGreeter.sol에 다음 코드를 작성하세요.

```
pragma solidity 0.5.6;
contract Mortal {
    /* 주소 타입의 소유자(owner) 변수 정의 */
    address payable owner;
    /* 이 함수는 초기화 시점에 실행되어 컨트랙트 소유자를 설정합니다 */
    constructor () public { owner = msg.sender; }
    /* 컨트랙트에서 자금을 회수하는 함수 */
    function kill() public payable { if (msg.sender == owner) selfdestruct(owner); }
}

contract KlaytnGreeter is Mortal {
    /* 문자열 타입의 변수 greeting 정의 */
    string greeting;
    /* 이 함수는 컨트랙트가 실행될 때 작동합니다 */
    constructor (string memory _greeting) public {
        greeting = _greeting;
    }
    /* 주(Main) 함수 */
    function greet() public view returns (string memory) {
        return greeting;
    }
}
```

## 마이그레이션(Migration) 스크립트 수정 <a href="#modifying-the-migration-script" id="modifying-the-migration-script"></a>

```bash
$ cd ..
$ cd migrations
$ vi 1_initial_migration.js
```

`1_initial_migration.js`를 다음과 같이 수정합니다.

```javascript
const Migrations = artifacts.require("./Migrations.sol");
const KlaytnGreeter = artifacts.require("./KlaytnGreeter.sol");
module.exports = function(deployer) {
  deployer.deploy(Migrations);
  deployer.deploy(KlaytnGreeter, 'Hello, Klaytn');
};
```

## 트러플을 사용하여 스마트 컨트랙트 배포 <a href="#deploying-a-smart-contract-using-truffle" id="deploying-a-smart-contract-using-truffle"></a>

truffle.js에 Klaytn의 네트워크 정보를 입력하세요.

**`경고`**: 현재 Klaytn Baobab 네트워크의 가스 가격이 25 Gpeb으로 고정되어 있습니다. (**다른 수치를 사용하려고 시도하면 오류가 반환됩니다**).

```bash
$ cd ..
$ vi truffle-config.js
```

아래와 같이 환경설정을 수정합니다.

```javascript
// truffle-config.js
module.exports = {
    networks: {
        klaytn: {
            host: '127.0.0.1',
            port: 8551,
            from: '0x75a59b94889a05c03c66c3c84e9d2f8308ca4abd', // 계정 주소를 입력하세요
            network_id: '1001', // Baobab 네트워크 id
            gas: 20000000, // 트랜잭션 가스 한도
            gasPrice: 25000000000, // Baobab의 gasPrice는 25 Gpeb입니다
        },
    },
    compilers: {
      solc: {
        version: "0.5.6"    // 컴파일러 버전을 0.5.6로 지정
      }
  }
};
```

다음 명령을 사용하여 컨트랙트를 배포하세요.

**참고**: 배포할 네트워크를 선택하기 위해 `--network`를, 덮어 쓰기위해 `--reset`을 사용하세요.

**참고**: Klaytn 노드가 실행 중인지 확인하세요.

컨트랙트 주소가 \`KlaytnGreeter: 뒤에 이어 표시됩니다.

```bash
$ truffle deploy --network klaytn --reset
Using network 'klaytn'.
Running migration: 1_initial_migration.js
  Deploying Migrations...
  ... 0x0f5108bd9e51fe6bf71dfc472577e3f55519e0b5d140a99bf65faf26830acfca
  Migrations: 0x97b1b3735c8f2326a262dbbe6c574a8ea1ba0b7d
  Deploying KlaytnGreeter...
  ... 0xcba53b6090cb4a118359b27293ba95116a8f35f66ae50fbd23ae1081ce9ffb9e
  KlaytnGreeter: [SAVE THIS ADDRESS!!] # this is your smart contract address
Saving successful migration to network...
  ... 0x14eb68727ca5a0ac767441c9b7ab077336f9311f71e9854d42c617aebceeec72
Saving artifacts...
```

**`경고`**: 계정이 잠겨 있으면 오류를 반환합니다.

```bash
Running migration: 1_initial_migration.js
  Replacing Migrations...
  ... undefined
Error encountered, bailing. Network state unknown. Review successful transactions manually.
Error: authentication needed: password or unlock
```

다음은 계정을 잠금 해제하는 방법입니다.

```javascript
> personal.unlockAccount('0x775a59b94889a05c03c66c3c84e9d2f8308ca4abd')
Unlock account 0x75a59b94889a05c03c66c3c84e9d2f8308ca4abd
Passphrase:
true
```

다음으로 갈 차례입니다. 다시 배포해보세요.


# Check the Deployment

## caver-js를 사용해 배포된 바이트 코드 확인 <a href="#checking-the-deployed-byte-code-using-caver-js" id="checking-the-deployed-byte-code-using-caver-js"></a>

배포된 스마트 컨트랙트의 바이트 코드를 확인하기 위해 `getCode`를 사용합니다.

먼저, 테스트 파일을 만들고 엽니다(open).

```bash
$ touch test-klaytn.js
$ open test-klaytn.js
```

다음 테스트 코드를 작성하세요. 방금 배포한 컨트랙트 주소를 입력해야 합니다.

```javascript
// test-klaytn.js
const Caver = require('caver-js');
const caver = new Caver('http://127.0.0.1:8551');
// 스마트 컨트랙트 주소 입력
const contractAddress = '0x65ca27ed42abeef230a37317a574058ff1372b34'
caver.klay.getCode(contractAddress).then(console.log);
```

코드를 실행하세요.

```bash
$ node test-klaytn.js
0x60806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806341c0e1b514610051578063cfae321714610068575b600080fd5b34801561005d57600080fd5b506100666100f8565b005b34801561007457600080fd5b5061007d610189565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100bd5780820151818401526020810190506100a2565b50505050905090810190601f1680156100ea5780820380516001836020036101000a031916815260200191505b509250505060405180...
```

## 배포된 스마트 컨트랙트의 함수 호출 <a href="#calling-functions-in-the-deployed-smart-contract" id="calling-functions-in-the-deployed-smart-contract"></a>

자바스크립트를 사용하여 컨트랙트의 `greet()`를 호출하세요.

**참고**: 스마트 컨트랙트에서 특정 함수를 호출하려면, ABI (Application Binary Interface) 파일이 필요합니다. 트러플이 컨트랙트를 배포하면, `./build/contracts/`에 `abi` 속성을 포함하는 .json 파일이 자동으로 생성됩니다.

위에서 작성한 테스트 코드에 다음 행을 추가하세요.

```javascript
// test-klaytn.js
const Caver = require('caver-js');
const caver = new Caver('http://127.0.0.1:8551');
// 스마트 컨트랙트 주소 입력
const contractAddress = '0x65ca27ed42abeef230a37317a574058ff1372b34'

caver.klay.getCode(contractAddress).then(console.log);
// 행 추가
const KlaytnGreeter = require('./build/contracts/KlaytnGreeter.json');
// 스마트 컨트랙트 주소 입력
const klaytnGreeter = new caver.klay.Contract(KlaytnGreeter.abi, contractAddress);
klaytnGreeter.methods.greet().call().then(console.log);
```

테스트 코드를 실행하세요.

```bash
$ node test-klaytn.js
0x60806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806341c0e1b514610051578063cfae321714610068575b600080fd5b34801561005d57600080fd5b506100666100f8565b005b34801561007457600080fd5b5061007d610189565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100bd5780820151... # This is from caver.klay.getCode
Hello, Klaytn # This is from KlyatnGreeter.methods.greet()
```

**결과로 "Hello, Klaytn"을 얻으면 작업을 완료한 것입니다. 축하합니다!**


# Account Management

**`경고`**: 비밀번호를 기억하세요. 계정 비밀번호를 잊어버린 경우, 해당 계정에 액세스할 수 없습니다. **여기에는** ***비밀번호 찾기*** **옵션이 없습니다. 절대 잊지 말아주세요.**

Klaytn은 개발자가 계정을 관리할 수 있도록 두 가지 편리한 명령행 도구인 `ken`과 `자바스크립트 콘솔`을 제공합니다. 개인키를 암호화되지 않은 형식으로 내보내는 것은 지원되지 않습니다.

## ken <a href="#ken" id="ken"></a>

Klaytn 엔드포인트 노드 바이너리 `ken`은 `account` 명령을 통해 계정 관리 기능을 제공합니다. `account` 명령으로 새 계정을 만들고, 기존의 모든 계정을 나열하고, 개인키를 새 계정으로 가져오고, 최신 키 형식으로 옮기거나(migrate), 암호를 변경할 수 있습니다.

### 사용법 <a href="#usage" id="usage"></a>

```bash
$ ken account <command> [options...] [arguments...]
```

**명령어**

```bash
$ ken account -help
...
COMMANDS:
     list    Print summary of existing accounts
     new     Create a new account
     update  Update an existing account
     import  Import a private key into a new account
...
```

`ken account <command> --help`로 하위 명령에 대한 정보를 얻을 수 있습니다.

```
$ ken account list --help
list [command options] [arguments...]

Print a short summary of all accounts

KLAY OPTIONS:
  --dbtype value                        Blockchain storage database type ("leveldb", "badger") (default: "leveldb")
  --datadir "/Users/ethan/Library/KEN"  Data directory for the databases and keystore
  --keystore                            Directory for the keystore (default = inside the datadir)

DATABASE OPTIONS:
  --db.no-partitioning  Disable partitioned databases for persistent storage
```

### 데이터 디렉토리 <a href="#data-directory" id="data-directory"></a>

키스토어 파일은 `<DATADIR>/keystore`에 저장됩니다. 아래와 같이 데이터 디렉토리를 지정할 수 있습니다. `--datadir` 옵션과 함께 `ken account` 명령을 실행하는 것이 권장됩니다. 계정을 엔드포인트 노드와 원활하게 공유할 수 있도록 `kend.conf`에 설정된 데이터 디렉토리가 `DATA_DIR`을 가리키도록 하세요.

```bash
$ ken account new --datadir <DATADIR>
$ ken account new --datadir "~/kend_home"
```

데이터 디렉토리를 지정하지 않으면, 기본 위치는 다음과 같습니다.

* Mac: `~/Library/KEN`
* Linux: `~/.ken`

## 자바스크립트 콘솔 <a href="#javascript-console" id="javascript-console"></a>

자바스크립트 콘솔에 연결하려면, EN이 실행 상태에 있어야합니다. 자세한 내용은 [EN 시작하기](/content/getting-started/quick-start/launch-an-en)를 살펴보세요. EN을 시작하고 다음과 같이 콘솔에 연결하세요.

### Usage <a href="#usage" id="usage"></a>

```bash
$ kend start
Starting kend: OK

$ ken attach ~/kend_home/klay.ipc
Welcome to the Klaytn JavaScript console!

instance: Klaytn/vX.X.X/XXXX-XXXX/goX.X.X
 datadir: ~/kend_home
 modules: admin:1.0 debug:1.0 governance:1.0 istanbul:1.0 klay:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0

>
```

**Commands**

`personal` 또는 `klay`를 입력해 사용 가능한 함수 목록을 가져옵니다. 이 튜토리얼에서는 다음 함수들을 확인할 수 있습니다.

```bash
> personal.newAccount()
> personal.importRawKey()
> personal.unlockAccount()
> klay.accounts
> klay.getBalance()
```

### Data Directory <a href="#data-directory" id="data-directory"></a>

계정을 만들 때 키스토어 파일은 `<DATADIR>/keystore`에 저장됩니다. `<DATADIR>`은 `kend.conf`에 설정된 `DATA_DIR`입니다. 주어진 예시와 함께 빠른 시작 가이드를 따랐다면, `~/kend_home`일 것입니다.


# Creating Accounts

## 새로운 계정 생성 <a href="#creating-a-new-account" id="creating-a-new-account"></a>

이렇게 하면 새 계정이 만들어지고 화면에 주소가 인쇄됩니다. 키스토어(keystore) 파일은 데이터 디렉토리 아래에 작성됩니다.

**Klaytn 키스토어 파일**

계정을 생성하면 키스토어 파일이 생성됩니다. 키스토어 파일은 트랜잭션을 서명하는 데 사용할 고유한 Klaytn 개인키의 암호화 버전입니다. 키스토어 파일 이름의 형식은 다음과 같습니다.

* `UTC--<created_at UTC ISO8601>-<address hex>`

Klaytn 노드들 간에 전체 디렉토리 또는 개별 키스토어 파일을 전송하는 것은 안전합니다. 다른 노드에서 노드에 키들을 추가하는 경우 계정 순서가 변경 될 수 있음에 주의하세요. 따라서 스크립트 또는 코드 조각의 인덱스(index)에 의존하지 않아야 합니다.

### ken <a href="#ken" id="ken"></a>

```bash
$ ken account new --datadir <DATADIR>
$ ken account new --password <passwordfile> --datadir <DATADIR>
$ ken account new --password <(echo $mypassword) --datadir <DATADIR>
```

**`경고`**: 암호 파일은 테스트 목적으로만 사용되어야 합니다. 암호를 파일에 저장하거나 다른 방법으로 노출시키는 것은 추천하지 않습니다. 비밀번호 파일에 비밀번호 플래그(flag)를 사용하는 경우, 파일을 본인 이외의 사람이 읽을 수 없고 나열할 수 없는지 확인하는 것이 좋습니다. 다음을 이용하면 이를 달성할 수 있습니다:

```bash
$ touch /path/to/password
$ chmod 700 /path/to/password
$ cat > /path/to/password
I type my pass here
^D
```

### JavaScript Console <a href="#javascript-console" id="javascript-console"></a>

콘솔에서 다음 함수를 호출하여 계정을 만들 수 있습니다:

```javascript
> personal.newAccount("passphrase")
```

계정은 암호화된 형식으로 저장됩니다. 앞으로 계정을 잠금 해제하려면 **반드시** 이 패스프레이즈를 기억하세요.

## 계정 가져오기 <a href="#importing-an-account" id="importing-an-account"></a>

키파일(keyfile)을 사용하여 계정을 가져올 수 있습니다. 키파일은 16진법으로 인코딩된 표준 EC raw 바이트이며 암호화되지 않은 개인키를 포함한다고 가정됩니다. 간단히 말해서, `0x`로 시작하지 않는 일반 텍스트의 개인키입니다.

지정된 키파일에서 암호화되지 않은 개인키를 가져오고, 새 계정을 만들고, 데이터 디렉토리 아래에 키스토어 파일을 생성한 다음, 콘솔에서 주소를 보여줍니다. 앞으로 계정을 잠금 해제하려면 반드시 암호를 기억하세요.

**참고**: 키스토어 파일을 다른 Klaytn 인스턴스에 직접 복사 할 수 있으면, 이 가져오기/내보내기 메커니즘이 필요하지 않습니다.

### ken <a href="#ken-1" id="ken-1"></a>

```bash
$ ken account import --datadir <datadir> <keyfile>
$ ken account import --password <passwordfile> --datadir <datadir> <keyfile>
```

### JavaScript Console <a href="#javascript-console-1" id="javascript-console-1"></a>

```bash
> personal.importRawKey('{private key}', 'mypassword')
"0xfa415bb3e6231f488ff39eb2897db0ef3636dd32"​

// Klaytn 지갑 키 사용
> personal.importRawKey('{private key}0x000x{address}', 'mypassword')
"0xfa415bb3e6231f488ff39eb2897db0ef3636dd32"
```


# Managing Accounts

## 계정 나열하기 <a href="#list-your-accounts" id="list-your-accounts"></a>

다음은 데이터 디렉토리에 생성된 모든 계정 목록을 반환합니다.

### ken <a href="#ken" id="ken"></a>

명령행에서, 다음을 사용하여 CLI를 호출하세요:

```bash
$ ken account list --datadir <DATADIR>
$ ken account list --datadir ~/kend_home
Account #0: {bfc22a57999459b0c2ce6337deb9287e7a970e02} keystore:///Users/username/kend_home/keystore/UTC--2019-03-26T07-02-58.524962000Z--bfc22a57999459b0c2ce6337deb9287e7a970e02
Account #1: {47bd2e9565cbe1789454718d6cf1778d7ea557aa} keystore:///Users/username/kend_home/keystore/UTC--2019-03-26T07-04-44.840061000Z--47bd2e9565cbe1789454718d6cf1778d7ea557aa
```

**참고**: 키스토어 파일을 다른 노드에서 복사하거나 파일을 제거하면 이 반환된 계정 목록의 순서가 달라질 수 있습니다. 따라서 인덱스에 의존하지 않도록 하거나, 키스토어 파일을 복사하거나 제거하는 경우에는 스크립트의 계정 인덱스들을 확인하고 업데이트하세요.

### JavaScript Console <a href="#javascript-console" id="javascript-console"></a>

콘솔을 사용하는 경우:

```javascript
> klay.accounts
["bfc22a57999459b0c2ce6337deb9287e7a970e02", "47bd2e9565cbe1789454718d6cf1778d7ea557aa"]
```

## 계정 잠금 해제 <a href="#unlock-accounts" id="unlock-accounts"></a>

비상호적으로 계정을 사용하려면, 잠금을 해제해야 합니다.

### ken <a href="#ken" id="ken"></a>

명령 행에서 쉼표로 구분된 계정(16진수 또는 인덱스) 목록인 `--unlock "{address},{address}"` 옵션을 인수로 사용하여 프로그래밍 방식으로 한 세션에 대해 계정을 잠금 해제하고 EN을 시작할 수 있습니다. This is useful if you want to use your account from dApps via RPC. `--unlock`은 목록에서 첫 번째 계정을 잠금 해제합니다. 이는 프로그래밍 방식으로 계정을 생성할 때 유용합니다. 잠금을 해제하기 위해 실제 계정을 알 필요는 없습니다.

계정을 생성하고 잠금이 해제된 계정과 함께 노드를 시작하세요.

```bash
$ ken account new --password <(echo this is not secret) --datadir <DATADIR>
$ ken --password <(echo "this is not secret") --unlock primary --datadir <DATADIR> --rpccorsdomain localhost --verbosity 6 2>> log.log
```

특정 계정이 잠금 해제 된 상태에서 노드를 시작하려면, 계정 목록의 주소 위치를 나타내는 주소 또는 인덱스를 사용할 수 있습니다(생성 순서에 해당).

```bash
$ ken --unlock "0" --datadir <DATADIR>
$ ken --unlock "2" --datadir <DATADIR>
$ ken --unlock "bfc22a57999459b0c2ce6337deb9287e7a970e02" --datadir <DATADIR>
```

명령행을 사용하면 여러 계정을 잠금 해제 할 수 있습니다. 이 경우 잠금 해제할 인수는 쉼표로 구분된 계정 주소 또는 인덱스 목록입니다.

```bash
$ ken --unlock "0x407d73d8a49eeb85d32cf465507dd71d507100c1,0,5,e470b1a7d2c9c5c6f03bbaa8fa20db6d404a0c32" --datadir <DATADIR>
```

이 구성을 비상호적으로 사용하는 경우, 비밀번호 파일에는 해당 계정의 대응되는 비밀번호가 한 줄에 하나씩 포함되어야 합니다.

### JavaScript Console <a href="#javascript-console" id="javascript-console"></a>

콘솔에서 (초를 단위로) 기간 동안 (한 번에 하나씩) 계정을 잠금 해제할 수도 있습니다.

```javascript
> personal.unlockAccount(address, "password", 300)
```

콘솔 히스토리가 기록되므로 암호 인자를 사용하지 않는 것이 좋습니다. 계정의 보안이 위협 받을 수 있습니다. 주의해주세요.

## 계정 잔액 확인 <a href="#check-account-balance" id="check-account-balance"></a>

### ken <a href="#ken" id="ken"></a>

n/a

### JavaScript Console <a href="#javascript-console" id="javascript-console"></a>

계정 잔액을 확인하려면 다음 단계를 따르십시오:

```javascript
> klay.fromPeb(klay.getBalance("{account}"), "KLAY")
6.5
```

자바스크립트 함수로 모든 잔액을 출력하세요:

```javascript
function checkAllBalances() {
    var totalBal = 0;
    for (var acctNum in klay.accounts) {
        var acct = klay.accounts[acctNum];

        var acctBal = klay.fromPeb(klay.getBalance(acct), "KLAY");
        totalBal += parseFloat(acctBal);

        console.log("klay.accounts[" + acctNum + "]: \t" + acct + " \tbalance: " + acctBal + "KLAY");

    }

    console.log("Total balance: " + totalBal + " KLAY");
};
```

다음으로 실행할 수 있습니다:

```javascript
> checkAllBalances();
klay.accounts[0]: 0xd1ade25ccd3d550a7eb532ac759cac7be09c2719  balance: 63.11848 KLAY
klay.accounts[1]: 0xda65665fc30803cb1fb7e6d86691e20b1826dee0  balance: 0 KLAY
klay.accounts[2]: 0xe470b1a7d2c9c5c6f03bbaa8fa20db6d404a0c32  balance: 1 KLAY
klay.accounts[3]: 0xf4dd5c3794f1fd0cdc0327a83aa472609c806e99  balance: 6 KLAY
```

`ken`을 다시 시작하면 이 함수가 사라지기 때문에, 자주 사용할 함수를 저장해놓으면 도움이 됩니다.

우선, `checkAllBalances()` 함수를 파일로 저장하세요. 예를 들면 `/Users/username/klayload.js`입니다. 그런 다음 대화식 콘솔에서 파일을 로드(load)합니다:

```javascript
> loadScript("/Users/username/klayload.js")
true
```

이 파일은 명령을 수동으로 입력한 것처럼 자바스크립트 환경을 수정할 것입니다. 자유롭게 시도해 보세요!


# Development Environment

**Klaytn 네트워크**

* Baobab 테스트넷
* Cypress 메인넷

**Endpoint Node**

* Your [Endpoint Node](/content/installation-guide/deployment/endpoint-node) is needed to connect to the Klaytn network and to issue an API call or send a transaction.
* `ken`은 Klaytn 엔드포인트 노드 바이너리입니다. `ken` exposes two interfaces, a [command-line interface](/content/installation-guide/deployment/endpoint-node/ken-cli-commands) and the [JSON-RPC APIs](/content/dapp/json-rpc). `ken`은 Linux와 MacOS에서 실행됩니다.
* `ken` CLI에는 여러 유틸리티 및 노드 관리 기능이 제공됩니다.

**스마트 컨트랙트 개발**

* [Remix Klaytn 플러그인](https://ide.klaytn.foundation) - 브라우저 기반 컴파일러 및 IDE인 리믹스의 Klaytn 플러그인
* [트러플](https://github.com/trufflesuite/truffle) - 솔리디티 스마트 컨트랙트 개발을 위한 오픈 소스 도구
* [Hardhat](https://hardhat.org/hardhat-runner/docs/getting-started) - A development environment for smart contracts and dApps.
* [Foundry](https://book.getfoundry.sh/) - Foundry is a smart contract development toolchain.

**Klaytn SDK**

* [caver-js](/content/dapp/sdk/caver-js) : Klaytn JSON-RPC API를 구현하는 자바스크립트 라이브러리.
* [caver-java](/content/dapp/sdk/caver-java) : Klaytn JSON-RPC API를 구현하는 자바 라이브러리.

**Klaytn 툴킷**

* [Klaytnscope](https://scope.klaytn.com/) - 블록 및 트랜잭션 탐색기
* [Klaytn Wallet](https://wallet.klaytn.com/) - 브라우저 기반 계정 관리 도구
* [Klaytn Contracts Wizard](https://wizard.klaytn.foundation/) - An interactive generator to bootstrap your smart contract and learn about Klaytn Contracts.


# Getting KLAY

### Baobab 테스트넷과 Faucet <a href="#baobab-testnet-and-faucet" id="baobab-testnet-and-faucet"></a>

**테스트넷 KLAY** Faucet은 Baobab 네트워크에서 실행됩니다. The faucet can be accessed from the [Baobab Klaytn Wallet](https://baobab.wallet.klaytn.foundation). 테스트넷 KLAY를 받으려면, 유효한 Klaytn 계정이 있어야 합니다.

* 개인키 또는 키스토어 파일을 사용하여 계정을 지갑에 로드(load)하세요. 테스트넷 KLAY는 로드된 계정으로 전송됩니다.
* `Run Faucet` 버튼을 누르면 5 테스트넷 KLAY가 전송되고 잔액이 업데이트될 것입니다. 24시간마다 한 번씩 각 계정에 대해 Faucet을 실행할 수 있습니다.

### KLAY 거래소 목록 <a href="#klay-exchange-list" id="klay-exchange-list"></a>

KLAY는 다양한 거래소에 등재되어 있습니다. 아래 링크에서 KLAY 거래소를 검색해보세요.

* [CoinGecko에 등재된 KLAY 거래소](https://www.coingecko.com/en/coins/klay#markets)
* [CoinMarketCap에 등재된 KLAY 거래소](https://coinmarketcap.com/currencies/klaytn/markets/)


# 스마트 컨트랙트

본 장에서는 스마트 컨트랙트 개발을 위한 개발 리소스들을 다룹니다.

Klaytn은 현재 스마트 컨트랙트를 작성하는 데에 [솔리디티(Solidity)](https://github.com/ethereum/solidity)를 기본 프로그래밍 언어로 지원하고 있습니다. 솔리디티는 이더리움의 스마트 컨트랙트 프로그래밍 언어 중 *사실상* 표준이고 많은 사용자를 가진 활발한 커뮤니티가 있기 때문에 Klaytn에서도 채택되었습니다. Klaytn 팀은 사용자에게 친숙한 개발 경험을 제공하여 이더리움 DApp 개발자들이 쉽게 Klaytn에서 실험을 하거나 그들의 프로젝트를 Klaytn으로 옮길 수 있도록 하였습니다.

앞으로 Klaytn은 다른 프로그래밍 언어로 작성된 스마트 컨트랙트 또한 지원할 계획입니다. Klaytn 팀은 개발자들이 선호할 만한 다른 유망한 프로그래밍 언어들을 다양하게 조사하고 있습니다.


# 솔리디티 - 스마트 컨트랙트 언어

솔리디티가 공식 웹 사이트에 이미 문서화되어 있으므로 이 장에서는 상위 개념, 개발 프로세스, 솔리디티로 작성된 예제만을 설명토록 하겠습니다. 솔리디티 언어 스펙과 구현에 대해서는 아래 [참조](#references)를 참고해주세요. 이 장의 내용은 [참조](#references)의 웹 사이트들을 기반으로 합니다.

## 솔리디티와 Klaytn <a href="#solidity-and-klaytn" id="solidity-and-klaytn"></a>

[솔리디티](https://github.com/ethereum/solidity)는 이더리움 플랫폼의 스마트 컨트랙트를 구현하기 위한 언어로, 고수준이고 정적인 컨트랙트 지향 언어입니다. 솔리디티는 원래 이더리움을 위해 설계되었지만 스마트 컨트랙트 작성을 위한 일반적인 언어로도 적합합니다. 따라서 Klaytn과 같은 블록체인 플랫폼에서도 사용할 수 있습니다.

Klaytn은 **London** Ethereum Virtual Machine (EVM)과 공식 호환 가능합니다. 다른 EVM 버전들과의 하위 호환성은 보장되지 않습니다. 따라서 Istanbul 타겟 옵션과 함께 솔리디티 코드를 컴파일하는 것을 권장드립니다. 자세한 내용은 [How to set the EVM version of solc](https://solidity.readthedocs.io/en/latest/using-the-compiler.html#setting-the-evm-version-to-target)를 참고해주세요.

{% hint style="success" %}
v1.7.0 Protocol Upgrade - incompatible changes including **Istanbul** hard fork items and Klaytn's own items. It has been enabled from block number `#75,373,312` in case of Baobab network and `#86,816,005` for the Cypress network.

v1.7.3 Protocol Upgrade - incompatible changes including Base Fee from the **London** hard fork. It has been enabled from block number `#80,295,291` in case of Baobab network and `#86,816,005` for the Cypress network.

v1.8.0 Protocol Upgrade - incompatible changes including Base Fee from the **London** hard fork. It has been enabled from block number `#86,513,895` in case of Baobab network and `#86,816,005` for the Cypress network.
{% endhint %}

Klaytn의 스마트 컨트랙트 개발을 위해 [Remix](https://remix.ethereum.org/)(브라우저 기반의 IDE) 와 [Truffle](https://github.com/trufflesuite/truffle)(개발 프레임워크) 과 같은 개발 도구를 활용할 수 있습니다. The Klaytn team will attempt to maintain compatibility between Ethereum's development tools and Klaytn's but may elect to provide the Klaytn smart contract developers with enhanced or updated versions of those tools when necessary.

It is convenient to utilize Remix or Truffle to develop smart contracts, but the Solidity compiler can be used locally, by building or installing it by following the instructions described in the web page below:

* [솔리디티 컴파일러 설치](https://docs.soliditylang.org/en/latest/installing-solidity.html)

Note that there are two command-line Solidity compilers:

* *solc*: 모든 기능을 갖춘 컴파일러입니다.
  * 솔리디티 문서에서도 안내하고 있습니다.
* *solcjs*: \_solc\_의 자바스크립트 버전입니다.
  * [solc-js](https://github.com/ethereum/solc-js)라는 별도의 프로젝트로 있습니다.
  * \_solcjs\_의 커맨드라인 옵션은 \_solc\_의 옵션과 호환되지 않습니다.

솔리디티를 시작하기에 유용한 기타 자료는 아래를 참고해주세요.

* [최고의 솔리디티 튜토리얼](https://medium.com/coinmonks/top-solidity-tutorials-4e7adcacced8)

## 스마트 컨트랙트 작성하기 <a href="#how-to-write-a-smart-contract" id="how-to-write-a-smart-contract"></a>

This section presents an example of Solidity source code to provide readers with an idea of how smart contracts look and how to write a contract. Note that the code included here is provided solely for explanatory purposes; it is not intended for production purposes. In the code, `(require)` means that the line is required for any Solidity source file while `(optional)` indicates that the line is not always needed. The symbol `Ln:` is not part of the Solidity code and is included here only to show the line numbers. Please do not include these symbols in source code intended for real use.

```
L01: pragma solidity 0.5.12;   // (required) version pragma
L02:
L03: import "filename";        // (optional) importing other source files
L04:
L05: // (optional) smart contract definition
L06: contract UserStorage {
L07:    mapping(address => uint) userData;  // state variable
L08:
L09:    function set(uint x) public {
L10:       userData[msg.sender] = x;
L11:    }
L12:
L13:    function get() public view returns (uint) {
L14:       return userData[msg.sender];
L15:    }
L16:
L17:    function getUserData(address user) public view returns (uint) {
L18:       return userData[user];
L19:    }
L20: }
```

The above code should be self-explanatory; thus people familiar with any other programming language can skip the following explanation in this section and jump to the next section. However, for those who do not gain a clear understanding of what the code does or those for whom Solidity is a first programming language, we include a short description of the source code below:

* 이중 슬래시 (`//`)로 시작하는 부분은 코드가 아니라 주석입니다. 코드의 특정 부분에 주석을 달아 설명을 첨부하는 데에 사용됩니다. 컴파일러는 이러한 주석을 무시합니다.
* `L01`의 `pragma`는 최소 컴파일러 버전을 나타냅니다. - `L03`의 `import`는 "`filename`"으로부터 모든 전역 심볼을 임포트합니다. `filename`은 실제 파일 이름이어야 합니다.
* `L05` - `L20`은 `UserStorage`라는 스마트 컨트랙트를 정의하는 부분입니다. `contract` 키워드는 컨트랙트의 이름 앞에 위치하여 이 코드가 스마트 컨트랙트임을 나타냅니다. 솔리디티의 컨트랙트는 객체 지향 언어의 클래스와 유사합니다. 컨트랙트는 상태 변수, 함수, 함수 변경자(modifier), 이벤트, 구조체 자료형, 열거식 자료형에 대한 선언을 포함할 수 있습니다. 또한 컨트랙트는 다른 컨트랙트로부터 상속될 수도 있습니다. 위 예제 코드에는 하나의 컨트랙트만 있지만, 한 솔리디티 파일에 여러 개의 컨트랙트가 정의될 수도 있습니다.
* `L07`의 `userData`는 맵핑 자료형의 상태 변수입니다. 상태 변수는 컨트랙트 스토리지에 영구적으로 저장됩니다. 상태 변수 `userData`는 `address`와 `uint` 값을 맵핑합니다. `address` 자료형은 20바이트 길이의 주소입니다 (Klaytn은 이더리움과 같이 20바이트 길이의 주소를 사용합니다).
* `L09`에서는 `x`를 메세지 발신자의 `userData`에 저장하는 퍼블릭 함수 `set`를 정의합니다. `msg.sender` 변수는 솔리디티에서 정의된 특별한 변수로 메세지 (*즉* current call) 발신자의 주소를 나타냅니다. `public` 키워드는 이 함수가 컨트랙트 인터페이스의 일부이며 내외부적으로(externally or internally) 호출될 수 있음을 나타냅니다.
* `L13`의 `get` 함수와 `L17`의 `getUserData` 함수는 `view`로 선언되었습니다. 이는 이 함수들의 상태 변수가 수정되면 안 된다는 것을 의미합니다. 이 함수들의 선언부에는 `returns (uint)`가 있습니다. 이는 함수가 반환하는 값의 자료형이 `uint`임을 의미합니다.

For more information concerning the syntax and semantics of the Solidity language, please refer to the [Solidity documentation](https://docs.soliditylang.org/).

## 컴파일, 배포, 실행하기 <a href="#how-to-compile-deploy-and-execute" id="how-to-compile-deploy-and-execute"></a>

One way to compile Solidity code is to use the command-line compiler *solc*. This compiler can produce various outputs, ranging from simple binaries and assembly to an abstract syntax tree (parse tree). Assuming that the code above is saved in `UserStorage.sol` (`L03` is excluded in the source file shown above), some examples of compiling the file `UserStorage.sol` are as follows.

```bash
$ solc --bin UserStorage.sol
```

* 이 명령은 컴파일 결과를 바이너리 *즉*, 바이트코드로 출력합니다.

```bash
solc -o output --bin --ast --asm UserStorage.sol
```

* 컴파일러는(`--bin`에 의해) 바이너리, (`--ast`에 의해) 추상 구문트리, (`--asm`에 의해) 어셈블리 코드를 각각 별도의 파일로 `output` 디렉토리에 생성합니다.

```bash
solc --optimize --bin UserStorage.sol
```

* 더 나은 성능을 위해 `--optimize` 플래그를 사용하여 컴파일 과정을 최적화할 수도 있습니다.

Some resources for compiling, deploying, and executing smart contracts are listed below.

* [솔리디티 커맨드라인 컴파일러 사용하기](https://docs.soliditylang.org/en/latest/using-the-compiler.html)
* [Remix를 사용하여 스마트 컨트랙트 컴파일하기](https://remix-ide.readthedocs.io/en/stable/compile.html)
* [Remix로 트랜잭션 실행하기](https://remix-ide.readthedocs.io/en/stable/run.html)
* [Remix Learneth 튜토리얼](https://remix-ide.readthedocs.io/en/latest/remix_tutorials_learneth.html)
* [트러플로 컨트랙트 컴파일하기](https://trufflesuite.com/docs/truffle/getting-started/compiling-contracts)
* [트러플로 컨트랙트 배포하기](https://trufflesuite.com/docs/truffle/getting-started/running-migrations)

NOTE: This section will be updated in the future.

## 스마트 컨트랙트 디버깅 <a href="#debugging-smart-contracts" id="debugging-smart-contracts"></a>

It is more difficult to debug Solidity code than to debug code written in other programming languages due to the lack of mature debugging tools. Below, we list some resources for Solidity debugging.

* [Remix로 트랜잭션 디버깅하기](https://remix-ide.readthedocs.io/en/latest/debugger.html)
* [Remix 트랜잭션 디버깅 튜토리얼](https://remix-ide.readthedocs.io/en/latest/tutorial_debug.html)
* [트러플로 컨트랙트 디버깅하기](https://trufflesuite.com/docs/truffle/getting-started/using-the-truffle-debugger/)

NOTE: This section will be updated in the future.

## 스마트 컨트랙트 모범 사례 <a href="#smart-contract-best-practices" id="smart-contract-best-practices"></a>

To eliminate security concerns and code quality issues from your smart contract, it is important to study and follow best practices in Solidity programming. Here, we show a reference for Solidity best practices.

* [스마트 컨트랙트 보안 모범 사례](https://github.com/ConsenSys/smart-contract-best-practices)

NOTE: This section will be updated in the future.

## References <a href="#references" id="references"></a>

* [솔리디티 GitHub 사이트](https://github.com/ethereum/solidity)
* [솔리디티 문서](https://solidity.readthedocs.io/en/latest/index.html)
* [Remix 문서](https://remix-ide.readthedocs.io/en/latest/)
* [트러플 문서](https://trufflesuite.com/docs/truffle/)


# 미리 컴파일된 컨트랙트

Klaytn provides several useful precompiled contracts. These contracts are implemented in the platform itself as a native implementation. 미리 컴파일된 컨트랙트 중 주소 0x01부터 0x08까지의 컨트랙트는 이더리움에서 구현된 것과 동일합니다. 여기에 추가로 Klaytn은 이더리움에 없는 새로운 기능을 지원하기 위해 주소 0x09부터 0x0B까지의 미리 컴파일된 컨트랙트를 제공합니다.

{% hint style="success" %}
NOTE: Three precompiled contract addresses have been changed, and **blake2F** was added after the `IstanbulEVM` protocol upgrade, or the "hard fork".

`IstanbulEVM` protocol upgrade block number is as follows.

* Baobab Testnet: `#75373312`
* Cypress Mainnet: `#86816005`

Contracts deployed before the protocol upgrade should use the original addresses.

* case 1) The contracts deployed in Baobab at block number `#75373310` recognizes 0x09, 0x0a, and 0x0b as addresses of vmLog, feePayer, and validateSender, respectively, and blake2f cannot be used.
* case 2) The contracts deployed in Baobab at block number `#75373314` recognizes 0x09 as the address of blake2f, and recognizes 0x3fd, 0x3fe, and 0xff as addresses of vmLog, feePayer, and validateSender.

If you want the previous document, please refer to [previous document](/content/smart-contract/precompiled-contracts/precompiled-contracts-previous).
{% endhint %}

| precompiled contract | addresses used in the contracts deployed before v1.7.0 protocol update activation | address used in the contracts deployed after v1.7.0 protocol update activation |
| -------------------- | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| vmLog                | 0x09                                                                              | 0x3fd                                                                          |
| feePayer             | 0x0a                                                                              | 0x3fe                                                                          |
| validateSender       | 0x0b                                                                              | 0x3ff                                                                          |

## Address 0x01: ecrecover(hash, v, r, s) <a href="#address-0x-01-ecrecover-hash-v-r-s" id="address-0x-01-ecrecover-hash-v-r-s"></a>

The address 0x01 implements ecrecover. It returns the address from the given signature by calculating a recovery function of ECDSA. Its function prototype is as follows:

```
function ecrecover(bytes32 hash, bytes8 v, bytes32 r, bytes32 s) returns (address);
```

## Address 0x02: sha256(data) <a href="#address-0x-02-sha-256-data" id="address-0x-02-sha-256-data"></a>

The address 0x02 implements SHA256 hash. It returns a SHA256 hash from the given data. Its function prototype is as follows:

```
function sha256(bytes data) returns (bytes32);
```

## Address 0x03: ripemd160(data) <a href="#address-0x-03-ripemd-160-data" id="address-0x-03-ripemd-160-data"></a>

The address 0x03 implements RIPEMD160 hash. It returns a RIPEMD160 hash from the given data. Its function prototype is as follows:

```
function ripemd160(bytes data) returns (bytes32);
```

## Address 0x04: datacopy(data) <a href="#address-0x-04-datacopy-data" id="address-0x-04-datacopy-data"></a>

The address 0x04 implements datacopy (i.e., identity function). It returns the input data directly without any modification. This precompiled contract is not supported by the Solidity compiler. The following code with inline assembly can be used to call this precompiled contract.

```
function callDatacopy(bytes memory data) public returns (bytes memory) {
    bytes memory ret = new bytes(data.length);
    assembly {
        let len := mload(data)
        if iszero(call(gas, 0x04, 0, add(data, 0x20), len, add(ret,0x20), len)) {
            invalid()
        }
    }

    return ret;
}     
```

## Address 0x05: bigModExp(base, exp, mod) <a href="#address-0x05-bigmodexp-base-exp-mod" id="address-0x05-bigmodexp-base-exp-mod"></a>

The address 0x05 implements the formula `base**exp % mod`. It returns the result from the given data. This precompiled contract is not supported by the Solidity compiler. The following code can be used to call this precompiled contract. Note that although this precompiled contract supports an arbitrary length of inputs, the below code uses a fixed length of inputs as an example.

```
function callBigModExp(bytes32 base, bytes32 exponent, bytes32 modulus) public returns (bytes32 result) {
    assembly {
        // free memory pointer
        let memPtr := mload(0x40)

        // length of base, exponent, modulus
        mstore(memPtr, 0x20)
        mstore(add(memPtr, 0x20), 0x20)
        mstore(add(memPtr, 0x40), 0x20)

        // assign base, exponent, modulus
        mstore(add(memPtr, 0x60), base)
        mstore(add(memPtr, 0x80), exponent)
        mstore(add(memPtr, 0xa0), modulus)

        // call the precompiled contract BigModExp (0x05)
        let success := call(gas, 0x05, 0x0, memPtr, 0xc0, memPtr, 0x20)
        switch success
        case 0 {
            revert(0x0, 0x0)
        } default {
            result := mload(memPtr)
        }
    }
}
```

## Address 0x06: bn256Add(ax, ay, bx, by) <a href="#address-0x-06-bn-256-add-ax-ay-bx-by" id="address-0x-06-bn-256-add-ax-ay-bx-by"></a>

The address 0x06 implements a native elliptic curve point addition. It returns an elliptic curve point representing `(ax, ay) + (bx, by)` such that (ax, ay) and (bx, by) are valid points on the curve bn256. This precompiled contract is not supported by the Solidity compiler. The following code can be used to call this precompiled contract.

```
function callBn256Add(bytes32 ax, bytes32 ay, bytes32 bx, bytes32 by) public returns (bytes32[2] memory result) {
    bytes32[4] memory input;
    input[0] = ax;
    input[1] = ay;
    input[2] = bx;
    input[3] = by;
    assembly {
        let success := call(gas, 0x06, 0, input, 0x80, result, 0x40)
        switch success
        case 0 {
            revert(0,0)
        }
    }
}
```

## Address 0x07: bn256ScalarMul(x, y, scalar) <a href="#address-0x-07-bn-256-scalarmul-x-y-scalar" id="address-0x-07-bn-256-scalarmul-x-y-scalar"></a>

The address 0x07 implements a native elliptic curve multiplication with a scalar value. It returns an elliptic curve point representing `scalar * (x, y)` such that (x, y) is a valid curve point on the curve bn256. This precompiled contract is not supported by the Solidity compiler. The following code can be used to call this precompiled contract.

```
function callBn256ScalarMul(bytes32 x, bytes32 y, bytes32 scalar) public returns (bytes32[2] memory result) {
    bytes32[3] memory input;
    input[0] = x;
    input[1] = y;
    input[2] = scalar;
    assembly {
        let success := call(gas, 0x07, 0, input, 0x60, result, 0x40)
        switch success
        case 0 {
            revert(0,0)
        }
    }
}
```

## Address 0x08: bn256Pairing(a1, b1, a2, b2, a3, b3, ..., ak, bk) <a href="#address-0x-08-bn-256-pairing-a-1-b-1-a-2-b-2-a-3-b-3-ak-bk" id="address-0x-08-bn-256-pairing-a-1-b-1-a-2-b-2-a-3-b-3-ak-bk"></a>

The address 0x08 implements elliptic curve paring operation to perform zkSNARK verification. For more information, see [EIP-197](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-197.md). This precompiled contract is not supported by the Solidity compiler. The following code can be used to call this precompiled contract.

```
function callBn256Pairing(bytes memory input) public returns (bytes32 result) {
    // input is a serialized bytes stream of (a1, b1, a2, b2, ..., ak, bk) from (G_1 x G_2)^k
    uint256 len = input.length;
    require(len % 192 == 0);
    assembly {
        let memPtr := mload(0x40)
        let success := call(gas, 0x08, 0, add(input, 0x20), len, memPtr, 0x20)
        switch success
        case 0 {
            revert(0,0)
        } default {
            result := mload(memPtr)
        }
    }
}
```

## Address 0x09: blake2F(rounds, h, m, t, f) <a href="#address-0x-3fc-vmlog-str" id="address-0x-3fc-vmlog-str"></a>

The address 0x09 implements BLAKE2b F compression function. For more information, see [EIP-152](https://eips.ethereum.org/EIPS/eip-152). This precompiled contract is not supported by the Solidity compiler. The following code can be used to call this precompiled contract.

```
function callBlake2F(uint32 rounds, bytes32[2] memory h, bytes32[4] memory m, bytes8[2] memory t, bool f) public view returns (bytes32[2] memory) {
    bytes32[2] memory output;

    bytes memory args = abi.encodePacked(rounds, h[0], h[1], m[0], m[1], m[2], m[3], t[0], t[1], f);

    assembly {
        if iszero(staticcall(not(0), 0x09, add(args, 32), 0xd5, output, 0x40)) {
            revert(0, 0)
        }
    }

    return output;
}
```

## 0x3fd 주소: vmLog(str) <a href="#address-0x-3fc-vmlog-str" id="address-0x-3fc-vmlog-str"></a>

The address 0x3FD prints the specified string `str` to a specific file or passes it to the logger module. For more information, see [debug\_setVMLogTarget](/content/dapp/json-rpc/api-references/debug/logging#debug_setvmlogtarget). Note that this precompiled contract should be used only for debugging purposes, and it is required to enable the `--vmlog` option when the Klaytn node starts. Also, the log level of the Klaytn node should be 4 or more to see the output of vmLog. This precompiled contract is not supported by the Solidity compiler. The following code can be used to call this precompiled contract.

```
function callVmLog(bytes memory str) public {
    address(0x3fd).call(str);
}
```

## 0x3fe 주소: feePayer() <a href="#address-0x-3fd-feepayer" id="address-0x-3fd-feepayer"></a>

The address 0x3FE returns a fee payer of the executing transaction. This precompiled contract is not supported by the Solidity compiler. The following code can be used to call this precompiled contract.

```
function feePayer() internal returns (address addr) {
    assembly {
        let freemem := mload(0x40)
        let start_addr := add(freemem, 12)
        if iszero(call(gas, 0x3fe, 0, 0, 0, start_addr, 20)) {
          invalid()
        }
        addr := mload(freemem)
    }
}
```

## 0x3ff 주소: validateSender() <a href="#address-0x-3fe-validatesender" id="address-0x-3fe-validatesender"></a>

The address 0x3FF validates the sender's signature with the message. Since Klaytn [decouples key pairs from addresses](/content/klaytn/design/accounts#decoupling-key-pairs-from-addresses), it is required to validate that a signature is properly signed by the corresponding sender. To do that, this precompiled contract receives three parameters:

* The sender's address to get the public keys
* The message hash that is used to generate the signature
* The signatures that are signed by the sender's private keys with the given message hash

The precompiled contract validates that the given signature is properly signed by the sender's private keys. Note that Klaytn natively support multi signatures, which means there can be multiple signatures. The signature must be 65 bytes long.

```
function ValidateSender(address sender, bytes32 msgHash, bytes sigs) public returns (bool) {
    require(sigs.length % 65 == 0);
    bytes memory data = new bytes(20+32+sigs.length);
    uint idx = 0;
    uint i;
    for( i = 0; i < 20; i++) {
        data[idx++] = (bytes20)(sender)[i];
    }
    for( i = 0; i < 32; i++ ) {
        data[idx++] = msgHash[i];
    }
    for( i = 0; i < sigs.length; i++) {
        data[idx++] = sigs[i];
    }
    assembly {
        // skip length header.
        let ptr := add(data, 0x20)
        if iszero(call(gas, 0x3ff, 0, ptr, idx, 31, 1)) {
          invalid()
        }
        return(0, 32)
    }
}
```


# 미리 컴파일된 컨트랙트 (구 버전 문서)

Klaytn은 몇 가지 유용한 미리 컴파일된 컨트랙트를 제공합니다. 이러한 컨트랙트들은 플랫폼 자체에서 기본 구현되어 있습니다. 미리 컴파일된 컨트랙트 중 주소 0x01부터 0x08까지의 컨트랙트는 이더리움에서 구현된 것과 동일합니다. 여기에 추가로 Klaytn은 이더리움에 없는 새로운 기능을 지원하기 위해 주소 0x09부터 0x0B까지의 미리 컴파일된 컨트랙트를 제공합니다.

{% hint style="success" %}
NOTE: This document contains the gas table used before the activation of the protocol upgrade. If you want the latest document, please refer to [latest document](/content/smart-contract/precompiled-contracts).
{% endhint %}

## 주소 0x01: ecrecover(hash, v, r, s) <a href="#address-0x-01-ecrecover-hash-v-r-s" id="address-0x-01-ecrecover-hash-v-r-s"></a>

0x01 주소는 ecrecover 함수를 구현한 미리 컴파일된 컨트랙트입니다. ecrecover 함수는 어떤 서명을 입력받으면 ECDSA의 recovery 함수를 계산하여 주소를 반환합니다. 함수의 프로토타입은 다음과 같습니다.

```
function ecrecover(bytes32 hash, bytes8 v, bytes32 r, bytes32 s) returns (address);
```

## 주소 0x02: sha256(data) <a href="#address-0x-02-sha-256-data" id="address-0x-02-sha-256-data"></a>

0x02 주소는 SHA256 함수를 구현한 미리 컴파일된 컨트랙트입니다. SHA256 함수는 어떤 데이터를 입력받으면 SHA256 해시를 반환합니다. Its function prototype is as follows:

```
function sha256(bytes data) returns (bytes32);
```

## 주소 0x03: ripemd160(data) <a href="#address-0x-03-ripemd-160-data" id="address-0x-03-ripemd-160-data"></a>

0x03 주소는 RIPEMD160 함수를 구현한 미리 컴파일된 컨트랙트입니다. RIPEMD160 함수는 어떤 데이터를 입력받으면 SHA256 해시를 반환합니다. Its function prototype is as follows:

```
function ripemd160(bytes data) returns (bytes32);
```

## 주소 0x04: datacopy(data) <a href="#address-0x-04-datacopy-data" id="address-0x-04-datacopy-data"></a>

0x04 주소는 datacopy (즉, 항등함수)를 구현한 미리 컴파일된 컨트랙트입니다. datacopy 함수는 입력받은 데이터를 그대로 반환합니다. 이 미리 컴파일된 컨트랙트는 솔리디티 컴파일러에서 지원하지 않습니다. 대신 인라인 어셈블리가 있는 아래 코드를 사용하여 이 컨트랙트를 호출할 수 있습니다.

```
function callDatacopy(bytes memory data) public returns (bytes memory) {
    bytes memory ret = new bytes(data.length);
    assembly {
        let len := mload(data)
        if iszero(call(gas, 0x04, 0, add(data, 0x20), len, add(ret,0x20), len)) {
            invalid()
        }
    }

    return ret;
}     
```

## 주소 0x05: bigModExp(base, exp, mod) <a href="#address-0x05-bigmodexp-base-exp-mod" id="address-0x05-bigmodexp-base-exp-mod"></a>

0x05 주소는 `base**exp % mod`라는 공식을 구현한 미리 컴파일된 컨트랙트입니다. 이 공식에 데이터를 입력하여 얻은 결과를 반환합니다. This precompiled contract is not supported by the Solidity compiler. 대신 아래 코드를 사용하여 이 컨트랙트를 호출할 수 있습니다. 해당 컨트랙트는 실제로 임의 길이의 입력을 받을 수 있지만, 아래 예제에서는 고정 길이의 입력으로 되어 있습니다.

```
function callBigModExp(bytes32 base, bytes32 exponent, bytes32 modulus) public returns (bytes32 result) {
    assembly {
        // 사용 가능한 메모리 포인터
        let memPtr := mload(0x40)

        // base, exponent, modulus의 길이
        mstore(memPtr, 0x20)
        mstore(add(memPtr, 0x20), 0x20)
        mstore(add(memPtr, 0x40), 0x20)

        // base, exponent, modulus 할당
        mstore(add(memPtr, 0x60), base)
        mstore(add(memPtr, 0x80), exponent)
        mstore(add(memPtr, 0xa0), modulus)

        // 사전 컴파일된 컨트랙트 BigModExp (0x05) 호출
        let success := call(gas, 0x05, 0x0, memPtr, 0xc0, memPtr, 0x20)
        switch success
        case 0 {
            revert(0x0, 0x0)
        } default {
            result := mload(memPtr)
        }
    }
}
```

## 주소 0x06: bn256Add(ax, ay, bx, by) <a href="#address-0x-06-bn-256-add-ax-ay-bx-by" id="address-0x-06-bn-256-add-ax-ay-bx-by"></a>

0x06 주소는 타원 곡선 점 덧셈 연산(elliptic curve point addition)을 구현한 미리 컴파일된 컨트랙트입니다. 해당 연산은 타원 곡선 bn256 상의 유효한 두 점 (ax, ay)와 (bx, by)를 입력받아 타원 곡선 위의 점 `(ax, ay) + (bx, by)`를 결과로 반환합니다. This precompiled contract is not supported by the Solidity compiler. The following code can be used to call this precompiled contract.

```
function callBn256Add(bytes32 ax, bytes32 ay, bytes32 bx, bytes32 by) public returns (bytes32[2] memory result) {
    bytes32[4] memory input;
    input[0] = ax;
    input[1] = ay;
    input[2] = bx;
    input[3] = by;
    assembly {
        let success := call(gas, 0x06, 0, input, 0x80, result, 0x40)
        switch success
        case 0 {
            revert(0,0)
        }
    }
}
```

## 주소 0x07: bn256ScalarMul(x, y, scalar) <a href="#address-0x-07-bn-256-scalarmul-x-y-scalar" id="address-0x-07-bn-256-scalarmul-x-y-scalar"></a>

0x07 주소는 스칼라값의 타원 곡선 점 곱셈 연산을 구현한 미리 컴파일된 컨트랙트입니다. 해당 연산은 타원 곡선 bn256 상의 유효한 점 (x, y)을 입력받아 타원 곡선 위의 점 `scalar * (x, y)`를 결과로 반환합니다. This precompiled contract is not supported by the Solidity compiler. The following code can be used to call this precompiled contract.

```
function callBn256ScalarMul(bytes32 x, bytes32 y, bytes32 scalar) public returns (bytes32[2] memory result) {
    bytes32[3] memory input;
    input[0] = x;
    input[1] = y;
    input[2] = scalar;
    assembly {
        let success := call(gas, 0x07, 0, input, 0x60, result, 0x40)
        switch success
        case 0 {
            revert(0,0)
        }
    }
}
```

## 주소 0x08: bn256Pairing(a1, b1, a2, b2, a3, b3, ..., ak, bk) <a href="#address-0x-08-bn-256-pairing-a-1-b-1-a-2-b-2-a-3-b-3-ak-bk" id="address-0x-08-bn-256-pairing-a-1-b-1-a-2-b-2-a-3-b-3-ak-bk"></a>

0x08 주소는 zkSNARK 검증을 하기 위해 타원 곡선 페어링 연산을 구현한 미리 컴파일된 컨트랙트입니다. 자세한 내용은 [EIP-197](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-197.md)를 참고해주세요. This precompiled contract is not supported by the Solidity compiler. The following code can be used to call this precompiled contract.

```
function callBn256Pairing(bytes memory input) public returns (bytes32 result) {
    // 입력은 (G_1 x G_2)^k로부터 나온 (a1, b1, a2, b2, ..., ak, bk)의 일련화된 바이트 스트림입니다.
    uint256 len = input.length;
    require(len % 192 == 0);
    assembly {
        let memPtr := mload(0x40)
        let success := call(gas, 0x08, 0, add(input, 0x20), len, memPtr, 0x20)
        switch success
        case 0 {
            revert(0,0)
        } default {
            result := mload(memPtr)
        }
    }
}
```

## 주소 0x09: vmLog(str) <a href="#address-0x-09-vmlog-str" id="address-0x-09-vmlog-str"></a>

The address 0x09 prints the specified string `str` to a specific file or passes it to the logger module. For more information, see [debug\_setVMLogTarget](https://github.com/klaytn/klaytn-docs-ko/blob/main/docs/smart-contract/dapp/json-rpc/api-references/debug/logging.md#debug_setvmlogtarget). 이 컨트랙트는 오직 디버깅을 목적으로 사용되어야 하며, Klaytn 노드를 시작할 때 `--vmlog` 옵션을 활성화해야 사용할 수 있습니다. 또한 vmLog의 출력을 보려면 Klaytn 노드의 로깅 수준이 4 이상이어야 합니다. This precompiled contract is not supported by the Solidity compiler. The following code can be used to call this precompiled contract.

```
function callVmLog(bytes memory str) public {
    address(0x09).call(str);
}
```

## 주소 0x0A: feePayer() <a href="#address-0x-0-a-feepayer" id="address-0x-0-a-feepayer"></a>

The address 0x0A returns a fee payer of the executing transaction. This precompiled contract is not supported by the Solidity compiler. The following code can be used to call this precompiled contract.

```
function feePayer() internal returns (address addr) {
    assembly {
        let freemem := mload(0x40)
        let start_addr := add(freemem, 12)
        if iszero(call(gas, 0x0a, 0, 0, 0, start_addr, 20)) {
          invalid()
        }
        addr := mload(freemem)
    }
}
```

## 주소 0x0B: validateSender() <a href="#address-0x-0-b-validatesender" id="address-0x-0-b-validatesender"></a>

The address 0x0B validates the sender's signature with the message. Since Klaytn [decouples key pairs from addresses](https://github.com/klaytn/klaytn-docs-ko/blob/main/docs/smart-contract/klaytn/design/accounts.md#decoupling-key-pairs-from-addresses), it is required to validate that a signature is properly signed by the corresponding sender. 이를 위해 이 컨트랙트는 세 개의 매개 변수를 입력받습니다.

* 공개키를 가져오는 데에 사용되는 발신자의 주소
* 서명을 생성하는 데에 사용된 메세지의 해시
* 메세지의 해시를 발신자의 개인키로 서명한 서명 값

이 컨트랙트는 주어진 서명 값이 발신자의 개인키로 올바르게 서명된 것인지 검증합니다. Note that Klaytn natively support multi signatures, the signatures can be multiple. The length of a signature must be 65 byte long.

```
function ValidateSender(address sender, bytes32 msgHash, bytes sigs) public returns (bool) {
    require(sigs.length % 65 == 0);
    bytes memory data = new bytes(20+32+sigs.length);
    uint idx = 0;
    uint i;
    for( i = 0; i < 20; i++) {
        data[idx++] = (bytes20)(sender)[i];
    }
    for( i = 0; i < 32; i++ ) {
        data[idx++] = msgHash[i];
    }
    for( i = 0; i < sigs.length; i++) {
        data[idx++] = sigs[i];
    }
    assembly {
        // 길이를 나타내는 헤더는 건너뜁니다
        let ptr := add(data, 0x20)
        if iszero(call(gas, 0x0b, 0, ptr, idx, 31, 1)) {
          invalid()
        }
        return(0, 32)
    }
}
```


# IDE 및 도구

이 페이지는 Klaytn의 스마트 컨트랙트 개발을 돕는 개발 도구 목록을 보여줍니다.

#### [Remix Online IDE](https://github.com/klaytn/klaytn-docs-ko/blob/main/docs/toolkit/klaytn-ide.md) <a href="#remix-ide" id="remix-ide"></a>

* Remix Online IDE is a powerful toolset for developing, deploying, debugging, and testing EVM-compatible smart contracts. You can write, compile, deploy and execute smart contracts on Klaytn from Remix IDE, using Klaytn Plugin.

#### [Klaytn Contracts Wizard](https://wizard.klaytn.foundation/) <a href="#klaytn-contract-wizard" id="klaytn-contract-wizard"></a>

* Klaytn Contracts Wizard is an interactive generator to bootstrap your smart contract and learn about Klaytn Contracts. This is based on OpenZeppelin Wizard.

#### [Truffle](/content/smart-contract/ide-and-tools/truffle) <a href="#truffle" id="truffle"></a>

* Klaytn smart contracts written in Solidity can be compiled and deployed using Truffle. At the moment, Klaytn supports up to Truffle v5.0.26.

#### [Kaikas](/content/dapp/developer-tools/getting-started/kaikas) <a href="#kaikas" id="kaikas"></a>

* Kaikas is a browser extension wallet for the Klaytn Network. Kaikas empowers you to store and interact with KLAY and your Klaytn-based tokens. Kaikas also enables you to sign transactions from web-based Klaytn dApps in realtime.

#### [Klaytn Wallet](/content/dapp/developer-tools/getting-started/klaytn-wallet) <a href="#klaytn-wallet" id="klaytn-wallet"></a>

* Klaytn Wallet is a browser-based account management tool for the Decentralized Application (dApp) developers. You can create/load your accounts, review your account balance, and transfer KLAY. You can also register your own Klaytn tokens to test basic behaviors.

#### [Klaytnscope](/content/dapp/developer-tools/getting-started-2/klaytnscope) <a href="#klaytnscope" id="klaytnscope"></a>

* Klaytnscope is the block explorer for the Klaytn Network. You can browse and inspect your transactions on the browser.


# Truffle

## 트러플(Truffle)과의 호환성 <a href="#compatibility-with-truffle" id="compatibility-with-truffle"></a>

Klaytn에서는 솔리디티로 작성된 스마트 컨트랙트를 트러플을 통해 컴파일하고 배포할 수 있습니다. 현재 Klaytn은 트러플 최신 버전인 v5.0.26까지 지원합니다. 트러플에 대한 자세한 내용은 아래 웹 사이트를 참고해주세요.

* [트러플 개요](https://trufflesuite.com/docs/truffle/overview)
* [트러플 레포지토리](https://github.com/trufflesuite/truffle)

다음과 같이 트러플을 설치할 수 있습니다.

```
$ sudo npm install -g truffle
```

로컬 EN을 실행 중인 경우 트러플 프레임워크를 사용하여 직접 컨트랙트를 배포할 수 있습니다. 자세한 내용은 [링크](/content/getting-started/quick-start/deploy-a-smart-contract#deploying-a-smart-contract-using-truffle)를 참고해주세요.

원격 EN 노드로 배포하려면 [truffle-hdwallet-provider-klaytn](https://www.npmjs.com/package/truffle-hdwallet-provider-klaytn)을 사용해야 합니다.

## truffle-hdwallet-provider-klaytn 환경설정 <a href="#configuring-truffle-hdwallet-provider-klaytn" id="configuring-truffle-hdwallet-provider-klaytn"></a>

truffle-hdwallet-provider-klaytn은 truffle-hdwallet-provider에서 파생된 자바스크립트 HD 지갑 제공자입니다.

다음과 같이 설치하세요.

```
$ nvm use 10
$ yarn install truffle-hdwallet-provider-klaytn@1.0.18
```

```
$ nvm use 12 # for node v12 and higher
$ yarn install truffle-hdwallet-provider-klaytn@1.4.1
```

아래와 같이 `truffle-config.js`를 설정하세요.

### 니모닉(Mnemonic) 사용 <a href="#using-a-mnemonic" id="using-a-mnemonic"></a>

```javascript
const HDWalletProvider = require("truffle-hdwallet-provider-klaytn");

const mnemonic = "mountains supernatural bird ...";

module.exports = {
  networks: {
    development: {
      host: "localhost",
      port: 8551,
      network_id: "*", // Match any network id
    },
    klaytn: {
      provider: () => {
        const mnemonic = JSON.parse(
          fs.readFileSync(path.resolve(__dirname) + "/mnemonics.js")
        );

        return new HDWalletProvider(
          mnemonic,
          "https://public-en-baobab.klaytn.net",
          0,
          mnemonic.length
        );
      },
      network_id: "1001", //Klaytn baobab testnet's network id
      gas: "8500000",
      gasPrice: null,
    },
    kasBaobab: {
      provider: () => {
        const option = {
          headers: [
            {
              name: "Authorization",
              value:
                "Basic " +
                Buffer.from(accessKeyId + ":" + secretAccessKey).toString(
                  "base64"
                ),
            },
            { name: "x-chain-id", value: "1001" },
          ],
          keepAlive: false,
        };
        return new HDWalletProvider(
          mnemonic,
          new Caver.providers.HttpProvider(
            "https://node-api.klaytnapi.com/v1/klaytn",
            option
          )
        );
      },
      network_id: "1001", //Klaytn baobab testnet's network id
      gas: "8500000",
      gasPrice: "25000000000",
    },
    kasCypress: {
      provider: () => {
        const option = {
          headers: [
            {
              name: "Authorization",
              value:
                "Basic " +
                Buffer.from(accessKeyId + ":" + secretAccessKey).toString(
                  "base64"
                ),
            },
            { name: "x-chain-id", value: "8217" },
          ],
          keepAlive: false,
        };
        return new HDWalletProvider(
          cypressMnemonic,
          new Caver.providers.HttpProvider(
            "https://node-api.klaytnapi.com/v1/klaytn",
            option
          )
        );
      },
      network_id: "8217", //Klaytn baobab testnet's network id
      gas: "8500000",
      gasPrice: "25000000000",
    },
    baobab: {
      provider: () => {
        return new HDWalletProvider(mnemonic, "http://your.baobab.en:8551");
      },
      network_id: "1001", //Klaytn baobab testnet's network id
      gas: "8500000",
      gasPrice: null,
    },
    cypress: {
      provider: () => {
        return new HDWalletProvider(mnemonic, "http://your.cypress.en:8551");
      },
      network_id: "8217", //Klaytn mainnet's network id
      gas: "8500000",
      gasPrice: null,
    },
  },
};
```

### 개인키(Private Key) 사용 <a href="#using-a-private-key" id="using-a-private-key"></a>

```javascript
const HDWalletProvider = require("truffle-hdwallet-provider-klaytn");

const privateKey = "0x123 ...";

module.exports = {
  networks: {
    development: {
      host: "localhost",
      port: 8551,
      network_id: "*", // Match any network id
    },
    klaytn: {
      provider: () => {
        const pks = JSON.parse(
          fs.readFileSync(path.resolve(__dirname) + "/privateKeys.js")
        );

        return new HDWalletProvider(
          pks,
          "https://public-en-baobab.klaytn.net",
          0,
          pks.length
        );
      },
      network_id: "1001", //Klaytn baobab testnet's network id
      gas: "8500000",
      gasPrice: null,
    },
    kasBaobab: {
      provider: () => {
        const option = {
          headers: [
            {
              name: "Authorization",
              value:
                "Basic " +
                Buffer.from(accessKeyId + ":" + secretAccessKey).toString(
                  "base64"
                ),
            },
            { name: "x-chain-id", value: "1001" },
          ],
          keepAlive: false,
        };
        return new HDWalletProvider(
          privateKey,
          new Caver.providers.HttpProvider(
            "https://node-api.klaytnapi.com/v1/klaytn",
            option
          )
        );
      },
      network_id: "1001", //Klaytn baobab testnet's network id
      gas: "8500000",
      gasPrice: "25000000000",
    },
    kasCypress: {
      provider: () => {
        const option = {
          headers: [
            {
              name: "Authorization",
              value:
                "Basic " +
                Buffer.from(accessKeyId + ":" + secretAccessKey).toString(
                  "base64"
                ),
            },
            { name: "x-chain-id", value: "8217" },
          ],
          keepAlive: false,
        };
        return new HDWalletProvider(
          cypressPrivateKey,
          new Caver.providers.HttpProvider(
            "https://node-api.klaytnapi.com/v1/klaytn",
            option
          )
        );
      },
      network_id: "8217", //Klaytn baobab testnet's network id
      gas: "8500000",
      gasPrice: "25000000000",
    },
    baobab: {
      provider: () => {
        return new HDWalletProvider(privateKey, "http://api.baobab.klaytn.net:8651");
      },
      network_id: "1001", //Klaytn baobab testnet's network id
      gas: "8500000",
      gasPrice: null,
    },
    cypress: {
      provider: () => {
        return new HDWalletProvider(privateKey, "https://public-en-cypress.klaytn.net");
      },
      network_id: "8217", //Klaytn mainnet's network id
      gas: "8500000",
      gasPrice: null,
    },
  },
};
```

**경고: 니모닉 및 개인키가 노출되지 않도록 주의하세요.**

Klaytn에 배포

```bash
$ truffle deploy --network baobab  # testnet
$ truffle deploy --network cypress # mainnet
```

Klaytn에 트랜잭션 생성하기 ([Truffle Docs quick start - Creating a project](https://www.trufflesuite.com/docs/truffle/quickstart#creating-a-project)의 예시 사용)

```bash
$ truffle console --network baobab
truffle(baobab)> Migrations.deployed().then(function(instance) {return instance.setCompleted(3)}) // making transaction
{
  tx: '0x734676311194c1ab8e004e2990e414b7b47a9d0a8506682707f5db03fa6dcee0',
  receipt: {
    blockHash: '0xdf9d77ef893a70b3a3f073525cdf5b2ee36620a3ac81815437788e4cf121678d',
    blockNumber: 65284860,
    contractAddress: null,
    from: '0x50c82047a414d2aad88ae67a5f02c311d2d86e69',
    gas: '0x500000',
    gasPrice: '0x5d21dba00',
    gasUsed: 27001,
    input: '0xfdacd5760000000000000000000000000000000000000000000000000000000000000003',
    logs: [],
    logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
    nonce: '0x1047',
    senderTxHash: '0x734676311194c1ab8e004e2990e414b7b47a9d0a8506682707f5db03fa6dcee0',
    signatures: [ [Object] ],
    status: true,
    to: '0x69527b5f0078ae1757b631af155fa9be21ef6a85',
    transactionHash: '0x734676311194c1ab8e004e2990e414b7b47a9d0a8506682707f5db03fa6dcee0',
    transactionIndex: 0,
    type: 'TxTypeLegacyTransaction',
    typeInt: 0,
    value: '0x0',
    cumulativeGasUsed: undefined,
    rawLogs: []
  },
  logs: []
}

truffle(baobab)> Migrations.deployed().then(function(instance) {return instance.last_completed_migration.call()}) // read public variable
BN { negative: 0, words: [ 3, <1 empty item> ], length: 1, red: null }
```


# 샘플 컨트랙트


# KlaytnGreeter

`KlaytnGreeter`는 인사말 메시지를 반환하는 간단한 컨트랙트입니다. 컨트랙트가 배포될 때 인사말 메시지가 설정됩니다.

## KlaytnGreeter 작성 <a href="#writing-klaytngreeter" id="writing-klaytngreeter"></a>

```
pragma solidity 0.5.6;
contract Mortal {
    /* address 타입의 owner변수 정의 */
    address payable owner;
    /* 이 함수는 초기화 시점에 실행되어 컨트랙트 소유자를 설정합니다 */
    constructor () public { owner = msg.sender; }
    /* 컨트랙트에서 자금을 회수하는 함수 */
    function kill() public { if (msg.sender == owner) selfdestruct(owner); }
}

contract KlaytnGreeter is Mortal {
    /* string 타입의 변수 greeting 정의 */
    string greeting;
    /* 이 함수는 컨트랙트가 생성될 딱 한번 실행됩니다 */
    constructor (string memory _greeting) public {
        greeting = _greeting;
    }
    /* 주(Main) 함수 */
    function greet() public view returns (string memory) {
        return greeting;
    }
}
```

## Deploying KlaytnGreeter using Remix Online IDE <a href="#deploying-klaytngreeter-using-klaytn-ide" id="deploying-klaytngreeter-using-klaytn-ide"></a>

* Please visit [Klaytn Plugin for Remix](https://ide.klaytn.foundation) and create a `KlaytnGreeter` contract. 완전한 소스 코드는 위에서 주어졌습니다.
* Prepare your account which will be used to deploy the contract.
  * If you do not have an account yet, create one at <https://baobab.wallet.klaytn.foundation/create> or <https://toolkit.klaytn.foundation/account/accountKeyLegacy>.
  * Get some test KLAY from the faucet - <https://baobab.wallet.klaytn.foundation/faucet>
* 초기 파라미터에 인사말 메시지를 넣어 컨트랙트를 배포하세요.
* 배포 후 IDE에서 `greet`를 호출할 수 있습니다.

## 참고 <a href="#references" id="references"></a>

For the details of contract deployment and the Remix Online IDE usage guideline, please refer to the following documents.

* [Remix Online IDE](/content/smart-contract/ide-and-tools#klaytn-ide)
* [Truffle](/content/smart-contract/ide-and-tools#truffle)
* [배포 가이드](/content/smart-contract/deploy-guide)


# ERC-20

## Introduction <a href="#introduction" id="introduction"></a>

이 튜토리얼은 [Klaytn 토큰 표준](/content/smart-contract/token-standard)([대체 가능 토큰 표준인 ERC-20과 호환](/content/smart-contract/token-standard#fungible-token-standard-kip-7))을 따르는 토큰을 만드는 방법을 소개합니다.

[ERC-20 토큰 표준](https://eips.ethereum.org/EIPS/eip-20)은 다음과 같이 2개의 이벤트와 9개의 메소드(3개의 선택적 메소드)를 정의합니다. ERC-20-호환 토큰은 다음의 인터페이스를 구현하기 위한 토큰 컨트랙트입니다.

```
function name() public view returns (string) //optional
function symbol() public view returns (string) //optional
function decimals() public view returns (uint8) //optional
function totalSupply() public view returns (uint256)
function balanceOf(address _owner) public view returns (uint256 balance)
function transfer(address _to, uint256 _value) public returns (bool success)
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)
function approve(address _spender, uint256 _value) public returns (bool success)
function allowance(address _owner, address _spender) public view returns (uint256 remaining)

event Transfer(address indexed _from, address indexed _to, uint256 _value)
event Approval(address indexed _owner, address indexed _spender, uint256 _value)
```

위의 인터페이스를 기반으로 개발자는 새로운 기능과 논리를 추가하여 토큰을 사용자 정의하고, Klaytn 네트워크에 배포할 수 있습니다. 자세한 내용은 공식 [ERC-20 문서](https://eips.ethereum.org/EIPS/eip-20)를 참조하세요.

이 튜토리얼에서는 ERC-20 호환 토큰인 `MyERC20.sol`을 구현할 것입니다. 이 토큰은 사전 정의된 양의 토큰을 발행하고 모든 토큰을 이를 배포한 컨트랙트 소유자에게 전송합니다.

`MyERC20.sol`은 OpenZeppelin의 ERC20 구현체를 기반으로 합니다. 이 튜토리얼에서 코드의 주요 부분은 [OpenZeppelin 2.3](https://github.com/OpenZeppelin/openzeppelin-solidity/releases/tag/v2.3.0)에서 가져온 것이며, 다음 솔리디티 파일은 `MyERC20.sol`을 구현하는 데 사용됩니다.

* <https://github.com/OpenZeppelin/openzeppelin-solidity/blob/v2.3.0/contracts/token/ERC20/IERC20.sol>
* <https://github.com/OpenZeppelin/openzeppelin-solidity/blob/v2.3.0/contracts/token/ERC20/ERC20.sol>
* <https://github.com/OpenZeppelin/openzeppelin-solidity/blob/v2.3.0/contracts/token/ERC20/ERC20Detailed.sol>
* <https://github.com/OpenZeppelin/openzeppelin-solidity/blob/v2.3.0/contracts/math/SafeMath.sol>

이 튜토리얼의 나머지 부분은 다음과 같이 구성됩니다.

* [1. ERC-20 스마트 컨트랙트 작성](/content/smart-contract/sample-contracts/erc-20/1-erc20)
  * 1.1 전체 `MyERC20` 코드와 `MyERC20` 코드의 전체 구조
  * 1.2 중요 함수 살펴보기
* [2. 스마트 컨트랙트 배포](/content/smart-contract/sample-contracts/erc-20/2-erc20)
  * 2.1 Klaytn IDE를 사용하여 스마트 컨트랙트 배포
  * 2.2 truffle을 사용하여 스마트 컨트랙트 배포
* [3. ERC-20 토큰과 Klaytn Wallet 간의 상호작용](/content/smart-contract/sample-contracts/erc-20/3-erc20)


# 1. ERC-20 스마트 컨트랙트 작성

## 1.1 MyERC20의 전체 구조 <a href="#id-1-1-overall-structure-of-myerc20" id="id-1-1-overall-structure-of-myerc20"></a>

`MyERC20.sol`의 전체 소스 코드는 아래에서 확인할 수 있습니다. 이 구현체에서 `constructor`는 컨트랙트 배포 시 미리 정의된 양의 토큰을 발행하기 위해 `_mint`를 호출합니다.

```
pragma solidity ^0.5.0;

/**
 * @dev EIP에 정의된 ERC20 표준 인터페이스 추가 함수를 포함하지 않습니다;
 * 이들에 접근하려면 `ERC20Detailed`을 확인하세요.
 */
interface IERC20 {
    function totalSupply() external view returns (uint256);

    function balanceOf(address account) external view returns (uint256);

    function transfer(address recipient, uint256 amount) external returns (bool);

    function allowance(address owner, address spender) external view returns (uint256);

    function approve(address spender, uint256 amount) external returns (bool);

    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    event Transfer(address indexed from, address indexed to, uint256 value);

    event Approval(address indexed owner, address indexed spender, uint256 value);
}

library SafeMath {
    /**
     * @dev 두 부호 없는 정수의 합을 반환합니다.
     * 오버플로우 발생 시 예외처리합니다.
     *
     * 솔리디티의 `+` 연산자를 대체합니다.
     *
     * 요구사항:
     * - 덧셈은 오버플로우될 수 없습니다.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev 두 부호 없는 정수의 차를 반환합니다.
     * 결과가 음수일 경우 오버플로우입니다.
     *
     * 솔리디티의 `-` 연산자를 대체합니다.
     *
     * 요구사항:
     * - 뺄셈은 오버플로우될 수 없습니다.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "SafeMath: subtraction overflow");
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev 두 부호 없는 정수의 곱을 반환합니다.
     * 오버플로우 발생 시 예외처리합니다.
     *
     * 솔리디티의 `*` 연산자를 대체합니다.
     *
     * 요구사항:
     * - 곱셈은 오버플로우될 수 없습니다.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // 가스 최적화: 이는 'a'가 0이 아님을 요구하는 것보다 저렴하지만,
        // 'b'도 테스트할 경우 이점이 없어집니다.
        // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev 두 부호 없는 정수의 몫을 반환합니다. 0으로 나누기를 시도할 경우
     * 예외처리합니다. 결과는 0의 자리에서 반올림됩니다.
     *
     * 솔리디티의 `/` 연산자를 대체합니다. 참고: 이 함수는
     * `revert` 명령코드(잔여 가스를 건들지 않음)를 사용하는 반면, 솔리디티는
     * 유효하지 않은 명령코드를 사용해 복귀합니다(남은 모든 가스를 소비).
     *
     * 요구사항:
     * - 0으로 나눌 수 없습니다.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        // 솔리디티는 0으로 나누기를 자동으로 검출하고 중단합니다.
        require(b > 0, "SafeMath: division by zero");
        uint256 c = a / b;
        // assert(a == b * c + a % b); // 이를 만족시키지 않는 경우가 없어야 합니다.

        return c;
    }

    /**
     * @dev 두 부호 없는 정수의 나머지를 반환합니다. (부호 없는 정수 모듈로 연산),
     * 0으로 나눌 경우 예외처리합니다.
     *
     * 솔리디티의 `%` 연산자를 대체합니다. 이 함수는 `revert`
     * 명령코드(잔여 가스를 건들지 않음)를 사용하는 반면, 솔리디티는
     * 유효하지 않은 명령코드를 사용해 복귀합니다(남은 모든 가스를 소비).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b != 0, "SafeMath: modulo by zero");
        return a % b;
    }
}

/**
 * @dev `IERC20` 인터페이스의 구현
 *
 * 이 구현은 토큰이 생성되는 방식과 무관합니다. 이는
 * 파생 컨트랙트에 `_mint`를 이용한 공급 메커니즘이 추가되어야 한다는 의미입니다.
 * 일반적인 메커니즘은 `ERC20Mintable`을 참조하세요.
 *
 * *자세한 내용은 가이드 [How to implement supply mechanisms]
 * (https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226)를 참고하세요.*
 *
 * 일반적인 OpenZeppelin 지침을 따랐습니다: 함수는 실패시 `false`를 반환하는 대신
 * 예외처리를 따릅니다. 그럼에도 이는 관습적이며
 * ERC20 애플리케이션의 기대에 반하지 않습니다.
 *
 * 또한, `transferFrom` 호출 시 `Approval` 이벤트가 발생됩니다.
 * 이로부터 애플리케이션은 해당 이벤트를 수신하는 것만으로
 * 모든 계정에 대한 허용량(allowance)을 재구성 할 수 있습니다. 이는 스펙에서 요구되지 않으므로, EIP에 대한 다른 구현체는
 * 이러한 이벤트를 발생하지 않을 수 있습니다.
 *
 * 마지막으로, 표준이 아닌 `decreaseAllowance` 및 `increaseAllowance`
 * 함수가 추가되어 허용량 설정과 관련해 잘 알려진 문제를
 * 완화했습니다. `IERC20.approve`를 참조하세요.
 */
contract MyERC20 is IERC20 {
    using SafeMath for uint256;

    mapping (address => uint256) private _balances;

    mapping (address => mapping (address => uint256)) private _allowances;

    // https://github.com/OpenZeppelin/openzeppelin-solidity/blob/v2.3.0/contracts/token/ERC20/ERC20Detailed.sol 시작 부분을 참고
    string private _name;
    string private _symbol;
    uint8 private _decimals;

    constructor (string memory name, string memory symbol, uint8 decimals) public {
        _name = name;
        _symbol = symbol;
        _decimals = decimals;

        _mint(msg.sender, 100000 * 10 ** uint256(decimals)); // 주의!
    }

    / **
     * @dev 토큰 이름을 반환합니다.
     */
    function name() public view returns (string memory) {
        return _name;
    }

    /**
     * @dev 주로 이름을 줄여서 표현한 토큰 심볼을
     * 반환합니다.
     */
    function symbol() public view returns (string memory) {
        return _symbol;
    }

    /**
     * @dev 사용자 표현을 위한 소수 자릿수를 반환합니다.
     * 예를 들어, `decimals`이  `2`인 경우, 505` 토큰은
     * 사용자에게 `5,05` (`505 / 10 ** 2`)와 같이 표시되어야 합니다.
     *
     * 토큰은 보통 18의 값을 취하며, 이는 Ether와 Wei의 관계를
     * 모방한 것입니다.
     *
     * > 이 정보는 디스플레이 목적으로만 사용됩니다.
     * `IERC20.balanceOf`와 `IERC20.transfer`를 포함해
     * 컨트랙트의 산술 연산에 어떠한 영향을 주지 않습니다.
     */
    function decimals() public view returns (uint8) {
        return _decimals;
    }
    // https://github.com/OpenZeppelin/openzeppelin-solidity/blob/v2.3.0/contracts/token/ERC20/ERC20Detailed.sol 끝 부분을 참고

    uint256 private _totalSupply;

    /**
     * @dev `IERC20.totalSupply`를 참조하세요.
     */
    function totalSupply() public view returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev `IERC20.balanceOf`를 참조하세요.
     */
    function balanceOf(address account) public view returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev `IERC20.transfer`를 참조하세요.
     *
     * 요구사항 :
     *
     * - `recipient`는 영 주소(0x0000...0)가 될 수 없습니다.
     * - 호출자의 잔고는 적어도 `amount` 이상이어야 합니다.
     */
    function transfer(address recipient, uint256 amount) public returns (bool) {
        _transfer(msg.sender, recipient, amount);
        return true;
    }

    /**
     * @dev `IERC20.allowance`를 참조하세요.
     */
    function allowance(address owner, address spender) public view returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev `IERC20.approve`를 참조하세요.
     *
     * 요구사항:
     *
     * - `spender`는 영 주소가 될 수 없습니다.
     */
    function approve(address spender, uint256 value) public returns (bool) {
        _approve(msg.sender, spender, value);
        return true;
    }

    /**
     * @dev `IERC20.transferFrom`를 참조하세요.
     *
     * 업데이트된 허용량을 나타내는 `Approval` 이벤트가 발생합니다. 이것은 EIP에서
     * 요구되는 바가 아닙니다. `ERC20`의 시작 부분에 있는 참고 사항을 참조하세요.
     *
     * 요구사항:
     * - `sender`와 `recipient`는 영 주소가 될 수 없습니다.
     * - `sender`의 잔고는 적어도 `value` 이상이어야 합니다.
     * - 호출자는 `sender`의 토큰에 대해 최소한 `amount` 만큼의 허용량을
     * 가져야 합니다.
     */
    function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount));
        return true;
    }

    /**
     * @dev 호출자에 의해 원자적(atomically)으로 `spender`에 승인된 허용량을 증가시킵니다.
     *
     * 이것은 `IERC20.approve`에 기술된 문제에 대한 완화책으로 사용될 수 있는
     * `approve`의 대안입니다.
     *
     * Emits an `Approval` event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
        _approve(msg.sender, spender, _allowances[msg.sender][spender].add(addedValue));
        return true;
    }

    /**
     * @dev 호출자에 의해 원자적으로 `spender`에 승인된 허용량을 감소시킵니다.
     *
     * This is an alternative to `approve` that can be used as a mitigation for
     * problems described in `IERC20.approve`.
     *
     * Emits an `Approval` event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender`는 호출자에 대해 최소한 `subtractedValue` 만큼의 허용량을
     * 가져야 합니다.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
        _approve(msg.sender, spender, _allowances[msg.sender][spender].sub(subtractedValue));
        return true;
    }

    /**
     * @dev `amount`만큼의 토큰을 `sender`에서 `recipient`로 옮깁니다.
     *
     * This is internal function is equivalent to `transfer`, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a `Transfer` event.
     *
     * 요구사항:
     *
     * - `sender`는 영 주소가 될 수 없습니다.
     * - `recipient`은 영 주소가 될 수 없습니다.
     * - `sender`의 잔고는 적어도 `amount` 이상이어야 합니다.
     */
    function _transfer(address sender, address recipient, uint256 amount) internal {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _balances[sender] = _balances[sender].sub(amount);
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(sender, recipient, amount);
    }

    /** @dev `amount`만큼의 토큰을 생성하고 `account`에 할당합니다.
     * 전체 공급량을 증가시킵니다.
     *
     * `from`이 영 주소로 설정된 `Transfer` 이벤트를 발생시킵니다.
     *
     * 요구사항:
     *
     * - `to`는 영 주소가 될 수 없습니다.
     */
    function _mint(address account, uint256 amount) internal {
        require(account != address(0), "ERC20: mint to the zero address");

        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(address(0), account, amount);
    }

     /**
     * @dev `account`로부터 `amount`만큼의 토큰을 파괴하고,
     * 전체 공급량을 감소시킵니다.
     *
     * `to`가 영 주소로 설정된 `Transfer` 이벤트를 발생시킵니다.
     *
     * 요구사항:
     *
     * - `account`는 영 주소가 될 수 없습니다.
     * - `account`는 적어도 `amount`만큼의 토큰이 있어야 합니다.
     */
    function _burn(address account, uint256 value) internal {
        require(account != address(0), "ERC20: burn from the zero address");

    _balances[account] = _balances[account].sub(value);
        _totalSupply = _totalSupply.sub(value);
        emit Transfer(account, address(0), value);
    }

    /**
     * @dev `owner`의 토큰에 대한 `spender`의 허용량을 `amount`만큼 설정합니다.
     *
     * This is internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an `Approval` event.
     *
     * 요구사항:
     *
     * - `owner`는 영 주소가 될 수 없습니다.
     * - `spender`는 영 주소가 될 수 없습니다.
     */
    function _approve(address owner, address spender, uint256 value) internal {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = value;
        emit Approval(owner, spender, value);
    }

    /**
     * @dev `account`로부터 `amount`만큼의 토큰을 파괴하고,
     * 호출자의 허용량으로부터 `amount`만큼을 공제합니다.
     *
     * `_burn` 및 `_approve`를 참조하세요.
     */
    function _burnFrom(address account, uint256 amount) internal {
        _burn(account, amount);
        _approve(account, msg.sender, _allowances[account][msg.sender].sub(amount));
    }
}
```

`MyERC20.sol`은 `IERC20` 인터페이스, `SafeMath` 라이브러리, `IERC20`를 구현하는 `MyERC20` 컨트랙트로 구성되었습니다.

* `IERC20` 인터페이스는 [ERC-20 스펙](https://eips.ethereum.org/EIPS/eip-20)에 명시된 필수 인터페이스를 정의합니다.
* `SafeMath` 라이브러리는 솔리디티의 `uint256` 타입에 대한 안전한 연산을 위해 오버플로우 검사를 추가한 솔리디티 산술 연산에 대한 래퍼(wrapper)를 정의합니다.
* `MyERC20`는 `IERC20` 인터페이스를 구현하고 [ERC-20 스펙](https://eips.ethereum.org/EIPS/eip-20)에 명시된 세 개의 추가적인 메서드(method)를 정의합니다.
  * ERC20에 더하여, `constructor`가 정의되었으며 이 생성자는 새로운 ERC20 토큰 이름과 심볼, 그리고 사전 정의된 양의 토큰을 발행하기 위해 사용됩니다. `constructor`는 첫 배포에서 한 번 호출됩니다.

## 1.2 중요한 메소드(method) 살펴보기 <a href="#id-1-2-take-a-look-at-important-methods" id="id-1-2-take-a-look-at-important-methods"></a>

몇 가지 중요한 메소드를 자세히 살펴 봅시다.

### (1) `function balanceOf(address account) external view returns (uint256);` <a href="#id-1-function-balanceof-address-account-external-view-returns-uint256" id="id-1-function-balanceof-address-account-external-view-returns-uint256"></a>

`balanceOf`는 ERC-20의 필수 메소드입니다. `balanceOf`는 주어진 주소의 잔액을 반환합니다.

```
    function balanceOf(address account) public view returns (uint256) {
        return _balances[account];
    }
```

`balanceOf`는 아래에 명시된 `mapping (address => uint256)`인 `_balances`에 저장된 키 `account`의 값을 반환합니다.

```
    mapping (address => uint256) private _balances;
```

만일 `_balances`에 대해 유효한 키 `account`가 없다면, `0`을 반환합니다.

### (2) `function transfer(address recipient, uint256 amount) external returns (bool);` <a href="#id-2-function-transfer-address-recipient-uint256-amount-external-returns-bool" id="id-2-function-transfer-address-recipient-uint256-amount-external-returns-bool"></a>

`transfer`는 ERC-20의 필수 메소드입니다. `transfer` 는 `amount` 만큼의 토큰을 `recipient`에게 전송하고, 반드시 `Transfer` 이벤트를 촉발해야 합니다. 이 함수는 메시지 호출자의 계정 잔액이 지불하기 위해 충분한 토큰을 가지고 있지 않으면 예외를 발생시켜야 합니다.

`transfer`는 아래와 같이 실제 전송 및 이벤트를 구현한 내부의 메소드 `_transfer`을 호출합니다.

```
    function transfer(address recipient, uint256 amount) public returns (bool) {
        _transfer(msg.sender, recipient, amount);
        return true;
    }
```

`_transfer`는 ERC-20의 메소드인 `transfer`의 실제 동작을 구현합니다.

또한, 아래와 같이 `require`를 사용해 영 주소로 또는 영 주소에서 토큰을 전송하지 못하게 합니다.

```
    function _transfer(address sender, address recipient, uint256 amount) internal {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _balances[sender] = _balances[sender].sub(amount);
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(sender, recipient, amount);
    }
```

### (3) `function approve(address spender, uint256 amount) external returns (bool);` <a href="#id-3-function-approve-address-spender-uint256-amount-external-returns-bool" id="id-3-function-approve-address-spender-uint256-amount-external-returns-bool"></a>

`approve`는 ERC-20의 필수 메소드입니다. `approve`는 `spender`가 당신의 계정으로부터 `amount` 한도 하에서 여러 번 출금하는 것을 허용합니다. 이 함수를 여러번 호출하면, 단순히 허용량을 `amount`으로 재설정합니다.

`approve`는 실제 `approve`의 동작을 구현한 내부의 메소드 `_approve`를 호출합니다. `msg.sender` 는 계정 `owner`로써 전달됩니다.

```
    function approve(address spender, uint256 value) public returns (bool) {
        _approve(msg.sender, spender, value);
        return true;
    }

    function _approve(address owner, address spender, uint256 value) internal {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = value;
        emit Approval(owner, spender, value);
    }
```

`_approve`는 특정 `address`로부터 `spender`에 대한 허용된 `value`를 유지하는 2차원 딕셔너리(dictionary)인 `_allowances`를 업데이트합니다.

```
    mapping (address => mapping (address => uint256)) private _allowances;
```

### (4) `function _mint(address account, uint256 amount) internal` <a href="#id-4-function-_mint-address-account-uint256-amount-internal" id="id-4-function-_mint-address-account-uint256-amount-internal"></a>

`_mint`는 ERC-20의 일부가 아닙니다. 그러나 새로운 ERC-20 토큰을 생성할 방법이 필요하며, 이 구현체에서 새 토큰을 생성하기 위해 아래와 같은 `_mint`가 필요합니다.

```
    function _mint(address account, uint256 amount) internal {
        require(account != address(0), "ERC20: mint to the zero address");

        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(address(0), account, amount);
    }
```

`_mint`는 컨트랙트 내부의 메소드이며 이 컨트랙트 안에서 호출할 수 있습니다.

`MyERC20.sol`에서 `_mint`는 스마트 컨트랙트를 배포할 때 사전 정의된 양의 토큰을 발행하기 위해 `constructor`에서 한 번만 호출됩니다.

스마트 컨트랙트를 배포한 후 추가 토큰을 발행하려면, `mint`와 같은 새로운 공개 메소드를 도입해야 합니다. 이 메소드는 오직 권한이 있는 사용자만이 발행할 수 있어야 하므로, 주의해서 구현해야 합니다.

더 자세한 내용을 위해서는 OpenZeppelin 예제 [ERC20Mintable.sol](https://github.com/OpenZeppelin/openzeppelin-solidity/blob/v2.3.0/contracts/token/ERC20/ERC20Mintable.sol)를 참조하세요.


# 2. 스마트 컨트랙트 배포

You can use Remix Online IDE or use Truffle to deploy `MyERC20` smart contract.

## 2.1 Deploying smart contract using Remix Online IDE <a href="#id-2-1-deploying-smart-contract-using-klaytn-ide" id="id-2-1-deploying-smart-contract-using-klaytn-ide"></a>

* Please visit [Klaytn Plugin for Remix](https://ide.klaytn.foundation) and create a `MyERC20` contract. 전체 소스 코드는 [ERC-20 스마트 컨트랙트 작성](/content/smart-contract/sample-contracts/erc-20/1-erc20)에서 가져왔습니다.
* 컨트랙트를 배포하는 데 사용할 계정을 준비하세요.
  * If you do not have an account yet, create one at <https://baobab.wallet.klaytn.foundation/create> or <https://toolkit.klaytn.foundation/account/accountKeyLegacy>.
  * Get some test KLAY from the faucet - <https://baobab.wallet.klaytn.foundation/faucet>
* `BAOBABTOKEN`의 배포 파라미터, `BAO` 및 `8`로 `MyERC20.sol`를 배포해봅시다.

![ERC20-1-배포](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-72da314e3b5217d1fa79f279a2c2636f869e9524%2Ferc20-1-deploy.png?alt=media\&token=2b033f24-941b-4c2f-977e-3d45df8e65d9)

After deploying, you can invoke `balanceOf` with your account, which was used to deploy the contract. 다음과 같이 `10000000000000` 토큰을 사용할 수 있음을 확인할 수 있습니다. Because you set `decimal` as `8` when deploying the contract above, it minted a fixed number of `100000` tokens in the constructor, with one token having a decimal value of `10^8`. `totalSupply` 메소드는 발행된 토큰의 총 공급량을 반환하며 이는 또한 `10000000000000`이어야 합니다.

![ERC20-2-소유자-토큰](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-9e0612f0d48b68ec28db082537749ca92b7dfe07%2Ferc20-2-owner_token.png?alt=media\&token=46f66aef-61b3-45ed-a100-cf8cf541cda5)

`MyERC20` is now live !

## 2.2 truffle을 사용하여 스마트 컨트랙트 배포 <a href="#id-2-2-deploying-smart-contract-using-truffle" id="id-2-2-deploying-smart-contract-using-truffle"></a>

환경에 [node.js](https://nodejs.org/)를 설치해야 합니다. 다양한 환경에서 패키지 매니저를 사용해 node.js를 설치하기 위해 [Installing Node.js via package manager](https://nodejs.org/en/download/package-manager/)를 살펴보시길 바랍니다.

```
$ mkdir klaytn
$ cd klaytn
$ npm init # initialize npm at the erc20token directory
$ npm install truffle@4.1.15
$ npm install caver-js@latest # installing caver-js
$ ln -s node_modules/truffle/build/cli.bundled.js truffle
$ export PATH=`pwd`:$PATH
```

이제 스마트 컨트랙트를 배포하는 데 필요한 truffle 및 caver-js를 설치했습니다.

`truffle`과 스마트 컨트랙트 `MyERC20.sol`을 준비합시다.

```
$ mkdir myerc20
$ cd myerc20
$ truffle init
```

이제 다음과 같은 디렉토리 구조를 가질 것입니다.

```
.
├── contracts
│   ├── Migrations.sol
├── migrations
│   └── 1_initial_migration.js
└── truffle-config.js
```

이제 `MyERC20.sol`를 작성하고 `contracts` 디렉토리에 배치하세요.

또한 `BAOBABTOKEN`의 초기 파라미터, `BAO` 및 `8`로 `MyERC20`를 배포하기 위한 아래의 `1_initial_migration.js`도 편집하세요. 토큰 이름은 `BAOBABTOKEN`으로 설정되었으며 토큰 심볼은 `BAO`입니다. 토큰의 소수점 값은 `10^8`입니다. 예를 들어 `BAOBABTOKEN`의 `totalSupply`를 요청할 때, `10^5`가 아닌, `10^13`를 반환함에 주의하세요. 왜냐하면 솔리디티는 부동 소수점을 지원하지 않기 때문에 토큰 수는 항상 작은 작은 액면가인 자연수로 표시됩니다.

```javascript
const Migrations = artifacts.require("./Migrations.sol");
const MyERC20 = artifacts.require("./MyERC20.sol");
module.exports = function(deployer) {
  deployer.deploy(Migrations);
  deployer.deploy(MyERC20, 'BAOBABTOKEN', 'BAO', 8);
};
```

또한 Klaytn 네트워크에 스마트 컨트랙트를 배포하기 위해 아래와 같이 `truffle-config.js`를 편집해야 합니다. This is the same step described in [Deploying a Smart Contract using Truffle](/content/getting-started/quick-start/deploy-a-smart-contract#deploying-a-smart-contract-using-truffle).

```
// truffle-config.js
module.exports = {
    networks: {
        baobab: {
            host: '127.0.0.1',
            port: 8551,
            from: '0xabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd', // enter your account address
            network_id: '1001', // Baobab network id
            gas: 20000000, // transaction gas limit
            gasPrice: 250000000000, // gasPrice of Baobab is 250 ston
        },
    },
    compilers: {
      solc: {
        version: "0.5.12"    // Specify compiler's version to 0.5.12
      }
  }
};
```

이제 모두 준비되었으며 아래와 같이 `MyERC20.sol`를 배포할 수 있습니다.

```
$ truffle deploy --network baobab --reset
Compiling ./contracts/MyERC20.sol...
Writing artifacts to ./build/contracts

Using network 'baobab'.

Running migration: 1_initial_migration.js
  Replacing Migrations...
  ... 0x5a947f076f4570dff8ff18b1ae3557e27dd69c92ce38a3c97fad8f5355914066
  Migrations: 0x0d737e9865e5fc4c1ff53744fd2c13c52a44b9bc
  Deploying MyERC20...
  ... 0x1571e80552dab1d67260e8914e06d9b16ccae16fb698c750f6a09aab12517bc1
  MyERC20: 0xc4c8257ED9B4eB6422fDe29B1eCe5Ce301e637e1
Saving successful migration to network...
  ... 0x5b984b3f79c425d80470a96d5badb857fc05e7f31d94423044ae3119c639aa77
Saving artifacts...
```

`MyERC20`를 배포하기 위한 트랜잭션 해시는 `0x1571e80552dab1d67260e8914e06d9b16ccae16fb698c750f6a09aab12517bc1`이며 `MyERC20`의 주소는 `0xc4c8257ED9B4eB6422fDe29B1eCe5Ce301e637e1`입니다.

이제 `MyERC20`가 활성화되었습니다!


# 3. 클레이튼 월렛에서 ERC-20 토큰 사용

You can use [Baobab Klaytn Wallet](https://baobab.wallet.klaytn.foundation) to query your balance and transfer the ERC-20 compatible `BAOBABTOKEN` you just deployed.

아래 배포된 `MyERC20` 컨트랙트의 주소를 사용하여 지갑에 ERC-20 호환 토큰을 추가할 수 있습니다.

![ERC20-3-토큰-추가](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-a799b5dcaedbe9a0d33a6c7cd7b78f296e1e481b%2Ferc20-3-add_token.png?alt=media\&token=80c36154-fff1-4d15-a786-794a28bffdfb)

지갑 애플리케이션에 ERC-20 토큰을 추가한 후, 아래와 같이 KLAY의 잔액에 추가로 `BAOBABTOKEN`의 잔액이 보일 것입니다. 계정에 `100000` `BAO` 토큰이 있음을 알 수 있습니다.

![ERC20-4-지갑-토큰](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-8330f5c7f4cdfc50d236bcf29089b88df86bcdbb%2Ferc20-4-wallet-token.png?alt=media\&token=eca99c21-7c76-4921-872b-d875d9163bc8)


# ERC-721

## Introduction <a href="#introduction" id="introduction"></a>

이 튜토리얼은 [Klaytn 토큰 표준](/content/smart-contract/token-standard)([대체 불가 토큰 표준인 ERC-721과 호환](/content/smart-contract/token-standard#non-fungible-token-standard-kip-17))을 따르는 토큰을 만드는 방법을 소개합니다.

[ERC-721 대체 불가능한 토큰 표준](https://eips.ethereum.org/EIPS/eip-721)은 아래와 같은 3개의 이벤트와 10개의 메소드를 정의합니다. ERC-721의 `supportsInterface`는 [ERC-165 표준 인터페이스 검출](https://eips.ethereum.org/EIPS/eip-165)에서 파생되었으며 ERC-165는 ERC-721의 일부분입니다. ERC-721 호환 토큰은 ERC-721 및 ERC-165 인터페이스를 구현한 토큰 컨트랙트입니다.

```solidity
event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);
event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);

function balanceOf(address _owner) external view returns (uint256);
function ownerOf(uint256 _tokenId) external view returns (address);
function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;
function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;
function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
function approve(address _approved, uint256 _tokenId) external payable;
function setApprovalForAll(address _operator, bool _approved) external;
function getApproved(uint256 _tokenId) external view returns (address);
function isApprovedForAll(address _owner, address _operator) external view returns (bool);
function supportsInterface(bytes4 interfaceID) external view returns (bool);
```

Based on above interface, developers may customize tokens by adding new features and logics, and deploy on Klaytn network. 자세한 내용은 공식 [ERC-721 스펙](https://eips.ethereum.org/EIPS/eip-721)을 참조하세요.

이 튜토리얼에서는 카드 타입의 대체 불가능한 토큰, 즉 ERC-721 토큰인 `MyERC721Card`의 구현체인 `MyERC721Card.sol`를 구현할 것입니다. 각 `MyERC721Card`는 이름과 레벨, 가령 레벨 1의 "왕(King)", 레벨 1의 "여왕(Queen)"을 가집니다.

`MyERC721Card.sol`은 OpenZeppelin의 ERC721 구현체를 기반으로 합니다. 이 튜토리얼에서 코드의 주요 부분은 [OpenZeppelin 2.3](https://github.com/OpenZeppelin/openzeppelin-solidity/releases/tag/v2.3.0)에서 가져왔습니다.

The rest of this tutorial is organized as follows.

* [1. ERC-721 스마트 컨트랙트 작성](/content/smart-contract/sample-contracts/erc-721/1-erc721)
  * 1.1 전체 `MyERC721Card` 코드와 `MyERC721Card` 코드의 전체 구조
  * 1.2 Take a look at important functions
* [2. Deploying smart contract](/content/smart-contract/sample-contracts/erc-721/2-erc721)
  * 2.1 Deploying smart contract using Remix Online IDE
  * 2.2 Deploying smart contract using truffle


# 1. ERC-721 스마트 컨트랙트 작성

## 1.1 MyERC721Card의 전체 구조 <a href="#id-1-1-overall-structure-of-myerc721card" id="id-1-1-overall-structure-of-myerc721card"></a>

`MyERC721Card.sol`의 전체 코드는 아래에서 확인할 수 있습니다.

```
pragma solidity ^0.5.0;

// https://github.com/OpenZeppelin/openzeppelin-solidity/blob/v2.3.0/contracts/utils/Address.sol
/**
 * @dev 주소 타입과 관련된 함수의 모음,
 */
library Address {
    /**
     * @dev 만일 `account` 가 컨트랙트라면 참(true)를 반환합니다.
     *
     * 이 테스트는 불완전하며, false-negatives가 있을 수 있습니다:
     * 컨트랙트의 생성자를 실행하는 중, 주소는 컨트랙트를 포함하지
     * 않은 것으로 보고될 것입니다.
     *
     * > 이 함수가 거짓(false)을 반환하는 주소가 외부 소유 계정(EOA)
     * 이며 컨트랙트가 아니라고 가정하는 것은 확실하지 않습니다.
     */
    function isContract(address account) internal view returns (bool) {
        // 코드는 생성자 실행이 완료되고 나서 저장되므로, 생성 중인
        // 컨트랙트에 대해 0을 반환하는 extcodesize에
        // 의존합니다.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
    }
}

// https://github.com/OpenZeppelin/openzeppelin-solidity/blob/v2.3.0/contracts/math/SafeMath.sol
/**
 * @dev 오버플로우 검사를 포함한 솔리디티의 산술 연산에 대한
 * 래퍼입니다.
 *
 * 솔리디티의 산술 연산은 오버플로우됩니다. 프로그래머는 일반적으로
 * 고수준 프로그래밍 언어의 일반적인 동작인 오버플로우가 에러를 발생시키는 것
 * 으로 가정하기 때문에, 이는 버그의 결과일 수 있습니다.
 * `SafeMath`는 연산이 오버플로우될 때 트랜잭션을 되돌려
 * 직관적으로 복원합니다.
 *
 * 확인되지 않은 연산 대신에 이 라이브러리를 사용하면 
 * 버그가 제거되므로, 항상 사용하는 것이 좋습니다.
 */
library SafeMath {
    /**
     * @dev 부호 없는 정수 두 개를 더한 값을 반환하고, 오버플로우를
     * 예외처리합니다.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "SafeMath: subtraction overflow");
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, "SafeMath: division by zero");
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b != 0, "SafeMath: modulo by zero");
        return a % b;
    }
}

// https://github.com/OpenZeppelin/openzeppelin-solidity/blob/v2.3.0/contracts/drafts/Counters.sol
/**
 * @title Counters
 * @author Matt Condon (@shrugs)
 * @dev 오직 1씩만 증가 또는 감소할 수 있는 카운터(counter)를 제공합니다. 이는 가령 매핑의 원소 수 추적,
 * ERC721 ID 발행, 또는 요청 ID 개수를 세는 데 사용할 수 있습니다.
 *
 * `using Counters for Counters.Counter;`으로 포함시킵니다.
 * 1씩 증가시키는 것으로 256 bit 정수를 오버플로우 시킬 수 없으므로, `increment`는 SafeMath
 * 오버플로우 체크를 스킵하고, 가스를 절약할 수 있습니다. 그러나 이는 기본적으로 `_value`가 직접 액세스되지 않는다는 가정하에 올바른 사용을 상정하고 있습니다.
 */
library Counters {
    using SafeMath for uint256;

    struct Counter {
        // 이 변수는 라이브러리의 사용자로부터 직접 액세스되어서는 안 됩니다: 상호작용은 라이브러리의 함수들로만
        // 제한되어져야 합니다. 솔리디티 v0.5.2부터, 비록 이 기능을 추가하는 제안이 있지만, 이는 강제될 수 없습니다:
        // https://github.com/ethereum/solidity/issues/4637를 참조하세요.
        uint256 _value; // 기본값: 0
    }

    function current(Counter storage counter) internal view returns (uint256) {
        return counter._value;
    }

    function increment(Counter storage counter) internal {
        counter._value += 1;
    }

    function decrement(Counter storage counter) internal {
        counter._value = counter._value.sub(1);
    }
}

/**
 * @dev [EIP](https://eips.ethereum.org/EIPS/eip-165)에 정의된
 * ERC165 표준의 인터페이스입니다.
 *
 * 구현체는 지원하는 컨트랙트 인터페이스를 선언할 수 있으며, 
 * 외부에서 (`ERC165Checker`) 이 함수를 호출해 지원 여부를 조회할 수 있습니다.
 *
 * 구현에 대해서는 `ERC165`를 참조하세요.
 */
interface IERC165 {
    /**
     * @dev 만일 컨트랙트가 `interfaceId`로 정의된 인터페이스를 구현했으면,
     * 참(true)을 반환합니다. ID 생성 방법에 대한 자세한 내용은 해당
     * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified)
     * 을 참조하세요.
     *
     * 이 함수 호출은 30000 가스보다 적게 사용할 것입니다.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

/**
 * @dev `IERC165` 인터페이스의 구현체.
 *
 * 컨트랙트는 이를 상속받을 수 있으며 `_registerInterface`를 호출해 인터페이스 지원을
 * 선언할 수 있습니다.
 */
contract ERC165 is IERC165 {
    /*
     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
     */
    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;

    /**
     * @dev 지원 여부에 대한 인터페이스 ID의 매핑
Mapping of interface ids to whether or not it's supported.
     */
    mapping(bytes4 => bool) private _supportedInterfaces;

    constructor () internal {
        // 파생된 컨트랙트는 고유한 인터페이스에 대한 지원만 등록하면 됩니다.
        // ERC165 자체에 대한 지원만 여기에서 등록합니다.
        _registerInterface(_INTERFACE_ID_ERC165);
    }

    /**
     * @dev `IERC165.supportsInterface`를 참조하세요.
     *
     * 시간 복잡도는 O(1)이며, 항상 30000 가스 미만을 사용하도록 보장합니다.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool) {
        return _supportedInterfaces[interfaceId];
    }

    /**
     * @dev 컨트랙트가 `interfaceId`로 정의한 인터페이스를 구현했음을
     * 등록합니다. 실제 ERC165 인터페이스의 지원은 자동으로 되며
     * 이 인터페이스 ID의 등록은 필요하지 않습니다.
     *
     * `IERC165.supportsInterface`를 참조하세요.
     *
     * 요구사항:
     *
     * - `interfaceId`는 ERC165 유효하지 않은 인터페이스(`0xffffffff`)일 수 없습니다.
     */
    function _registerInterface(bytes4 interfaceId) internal {
        require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
        _supportedInterfaces[interfaceId] = true;
    }
}

/**
 * @dev ERC721 호환 컨트랙트의 필수 인터페이스
 */
contract IERC721 is IERC165 {
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev `owner` 계정의 NFT의 개수를 반환합니다.
     */
    function balanceOf(address owner) public view returns (uint256 balance);

    /**
     * @dev `tokenId`에 의해 명시된 NFT의 소유자를 반환합니다.
     */
    function ownerOf(uint256 tokenId) public view returns (address owner);

    /**
     * @dev 특정 NFT (`tokenId`)를 한 계정(`from`)에서
     * 다른 계정(`to`)으로 전송합니다.
     *
     * 
     *
     * 요구사항:
     * - `from`, `to`는 0일 수 없습니다.
     * - `tokenId`는 `from`이 소유하고 있어야 합니다.
     * - 만일 호출자가 `from`이 아니라면, `approve` 또는
     * `setApproveForAll`를 통해 이 NFT의 전송을 허가받았어야 합니다.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId) public;
    /**
     * @dev 특정 NFT (`tokenId`)를 한 계정 (`from`)에서
     * 다른 계정(`to`)으로 전송합니다.
     *
     * 요구사항:
     * - 만일 호출자가 `from`이 아니라면, `approve` 또는
     * `setApproveForAll`를 통해 이 NFT를 전송을 허가받았어야 합니다.
     */
    function transferFrom(address from, address to, uint256 tokenId) public;
    function approve(address to, uint256 tokenId) public;
    function getApproved(uint256 tokenId) public view returns (address operator);

    function setApprovalForAll(address operator, bool _approved) public;
    function isApprovedForAll(address owner, address operator) public view returns (bool);


    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public;
} 

// https://github.com/OpenZeppelin/openzeppelin-solidity/blob/v2.3.0/contracts/token/ERC721/IERC721Receiver.sol
/**
 * @title ERC721 토큰 수신자 인터페이스
 * @dev ERC721 자산 컨트랙트로부터 safeTransfers를 지원하고 싶은
 * 컨트랙트를 위한 인터페이스입니다.
 */
contract IERC721Receiver {
    /**
     * @notice NFT 수신 처리
     * @dev ERC721 스마트 컨트랙트는 `safeTransfer` 후 수신자가 구현한
     * 이 함수를 호출합니다. 이 함수는 반드시 함수 선택자를 반환해야 하며,
     * 그렇지 않을 경우 호출자는 트랜잭션을 번복할 것입니다. 반환될 선택자는
     * `this.onERC721Received.selector`로 얻을 수 있습니다. 이 함수는
     * 전송을 번복하거나 거절하기 위해 예외를 발생시킬 수도 있습니다.
     * 참고: ERC721 컨트랙트 주소는 항상 메시지 발신자입니다.
     * @param operator `safeTransferFrom` 함수를 호출한 주소
     * @param from 이전에 토큰을 소유한 주소
     * @param tokenId 전송하고자 하는 NFT 식별자
     * @param data 특별한 형식이 없는 추가적인 데이터
     * @return bytes4 `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
     */
    function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data)
    public returns (bytes4);
}

// https://github.com/OpenZeppelin/openzeppelin-solidity/blob/v2.3.0/contracts/token/ERC721/ERC721.sol
contract ERC721 is ERC165, IERC721 {
    using SafeMath for uint256;
    using Address for address;
    using Counters for Counters.Counter;

    // `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`와 동일
    // `IERC721Receiver(0).onERC721Received.selector`로부터 얻을 수도 있습니다
    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;

    // 토큰 ID에서 소유자로의 매핑
    mapping (uint256 => address) private _tokenOwner;

    // 토큰 ID에서 승인된 주소로의 매핑
    mapping (uint256 => address) private _tokenApprovals;

    // 소유자에서 소유한 토큰 개수로의 매핑
    mapping (address => Counters.Counter) private _ownedTokensCount;

    // 소유자에서 운영자(operator) 승인 여부로의 매핑
    mapping (address => mapping (address => bool)) private _operatorApprovals;

    /*
     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231
     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e
     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3
     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc
     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465
     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c
     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd
     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e
     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde
     *
     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^
     *        0xa22cb465 ^ 0xe985e9c ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd
     */
    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;

    constructor () public {
        // ERC165를 통해 ERC721을 준수하도록 지원되는 인터페이스를 등록하세요
        _registerInterface(_INTERFACE_ID_ERC721);
    }

    /**
     * @dev 명시한 주소의 잔액을 얻습니다.
     * @param owner 잔액을 요청하는 주소
     * @return uint256 전달받은 주소가 보유한 수량
     */
    function balanceOf(address owner) public view returns (uint256) {
        require(owner != address(0), "ERC721: balance query for the zero address");

        return _ownedTokensCount[owner].current();
    }

    /**
     * @dev 명시된 토큰 ID의 소유자를 얻습니다.
     * @param tokenId uint256 소유자를 요청하는 토큰의 ID
     * @return address 주어진 토큰 ID의 현재 표시된 소유자
     */
    function ownerOf(uint256 tokenId) public view returns (address) {
        address owner = _tokenOwner[tokenId];
        require(owner != address(0), "ERC721: owner query for nonexistent token");

        return owner;
    }

    /**
     * @dev 주어진 토큰 ID의 전송을 다른 주소에게 허가합니다.
     * 영(zero) 주소는 승인된 주소가 없음을 나타냅니다.
     * 한 번에 하나의 승인된 주소만 있을 수 있습니다.
     * 토큰 소유자나 승인된 운영자만이 호출할 수 있습니다.
     * @param to address 주어진 토큰 ID에 대해 승인할 주소
     * @param tokenId uint256 승인하고자 하는 토큰 ID
     */
    function approve(address to, uint256 tokenId) public {
        address owner = ownerOf(tokenId);
        require(to != owner, "ERC721: approval to current owner");

        require(msg.sender == owner || isApprovedForAll(owner, msg.sender),
            "ERC721: approve caller is not owner nor approved for all"
        );

        _tokenApprovals[tokenId] = to;
        emit Approval(owner, to, tokenId);
    }

    /**
     * @dev 토큰 ID에 대해 승인된 주소를, 만일 설정된 주소가 없으면 0을 얻습니다.
     * 만일 토큰 ID가 존재하지 않는 경우 되돌려집니다.
     * @param tokenId uint256 승인된 주소를 요청하는 토큰의 ID
     * @return address 주어진 토큰 ID에 대해 현재 승인된 주소
     */
    function getApproved(uint256 tokenId) public view returns (address) {
        require(_exists(tokenId), "ERC721: approved query for nonexistent token");

        return _tokenApprovals[tokenId];
    }

    /**
     * @dev 주어진 운영자의 승인을 설정 또는 해제합니다.
     * 운영자는 발신자를 대신해 모든 토큰을 전송할 수 있도록 허가되었습니다.
     * @param to 승인을 설정하고자 하는 운영자의 주소
     * @param approved 설정하고자 하는 승인의 상태를 나타냅니다
     */
    function setApprovalForAll(address to, bool approved) public {
        require(to != msg.sender, "ERC721: approve to caller");

        _operatorApprovals[msg.sender][to] = approved;
        emit ApprovalForAll(msg.sender, to, approved);
    }

    /**
     * @dev 주어진 소유자에 대해 운영자가 승인되었는지 여부를 말해줍니다.
     * @param owner 승인을 조회하고자 하는 소유자 주소
     * @param operator 승인을 조회하고자 하는 운영자 주소
     * @return bool 주어진 운영자가 주어진 소유자로부터 승인되었는지 여부
     */
    function isApprovedForAll(address owner, address operator) public view returns (bool) {
        return _operatorApprovals[owner][operator];
    }

    /**
     * @dev 주어진 토큰 ID의 소유권을 다른 주소로 전송합니다.
     * 이 메소드는 사용하지 않는 것이 좋습니다. 가능하다면 `safeTransferFrom`을 사용하세요.
     * msg.sender는 소유자, 승인된 주소, 또는 운영자여야 합니다.
     * @param from 토큰의 현재 소유자
     * @param to 주어진 토큰 ID의 소유권을 받을 주소
     * @param tokenId 전송할 토큰의 uint256 ID
     */
    function transferFrom(address from, address to, uint256 tokenId) public {
        //solhint-disable-next-line max-line-length
        require(_isApprovedOrOwner(msg.sender, tokenId), "ERC721: transfer caller is not owner nor approved");

        _transferFrom(from, to, tokenId);
    }

    /**
     * @dev 주어진 토큰 ID의 소유권을 다른 주소로 안전하게 전송합니다.
     * 만일 목표 주소가 컨트랙트라면, 컨트랙트는 `onERC721Received`를 구현했어야만 합니다.
     * 이는 안전한 전송으로부터 호출되며 마법의 값
     * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`를 반환합니다;
     * 만일 다른 경우에는 전송이 되돌려집니다.
     * msg.sender는 소유자, 승인된 주소, 운영자여야 합니다
     * @param from 토큰의 현재 소유자
     * @param to 주어진 토큰 ID의 소유권을 받을 주소
     * @param tokenId 전송할 토큰의 uint256 ID
     */
    function safeTransferFrom(address from, address to, uint256 tokenId) public {
        safeTransferFrom(from, to, tokenId, "");
    }

    /**
     * @dev 주어진 토큰 ID의 소유권을 다른 주소로 안전하게 전송합니다.
     * 만일 목표 주소가 컨트랙트라면, 컨트랙트는 `onERC721Received`를 구현했어야만 합니다.
     * 이는 안전한 전송으로부터 호출되며 마법의 값
     * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`를 반환합니다;
     * 만일 다른 경우에는 전송이 되돌려집니다.
     * msg.sender는 소유자, 승인된 주소, 운영자여야 합니다
     * @param from 토큰의 현재 소유자
     * @param to 주어진 토큰 ID의 소유권을 받을 주소
     * @param tokenId 전송할 토큰의 uint256 ID
     * @param _data 안전한 전송 검사와 함께 전송하고자 하는 바이트 데이터
     */
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public {
        transferFrom(from, to, tokenId);
        require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
    }

    /**
     * @dev 지정한 토큰이 존재하는지 여부를 반환합니다.
     * @param tokenId uint256 존재를 조회하고자 하는 토큰의 ID
     * @return bool 토큰의 존재 여부
     */
    function _exists(uint256 tokenId) internal view returns (bool) {
        address owner = _tokenOwner[tokenId];
        return owner != address(0);
    }

    /**
     * @dev 지정된 납부자가 주어진 토큰 ID를 전송할 수 있는지 여부를 반환합니다.
     * @param spender 조회하고자 하는 납부자의 주소
     * @param tokenId uint256 전송하고자 하는 토큰 ID
     * @return bool msg.sender가 주어진 토큰 ID에 대해 승인되었는지,
     * 운영자인지, 또는 토큰의 소유자인지 여부
     */
    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) {
        require(_exists(tokenId), "ERC721: operator query for nonexistent token");
        address owner = ownerOf(tokenId);
        return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
    }

    /**
     * @dev 새 토큰을 발행하기 위한 내부 함수.
     * 주어진 토큰 ID가 이미 존재하면 되돌립니다.
     * @param to 발행된 토큰을 소유할 주소
     * @param tokenId uint256 발행될 토큰의 ID
     */
    function _mint(address to, uint256 tokenId) internal {
        require(to != address(0), "ERC721: mint to the zero address");
        require(!_exists(tokenId), "ERC721: token already minted");

        _tokenOwner[tokenId] = to;
        _ownedTokensCount[to].increment();

        emit Transfer(address(0), to, tokenId);
    }

    /**
     * @dev 특정 토큰을 소각하기 위한 내부 함수.
     * 토큰이 존재하지 않으면 되돌립니다.
     * 더 이상 사용되지 않으며, _burn(uint256)을 대신 사용하세요.
     * @param owner 소각할 토큰의 소유자
     * @param tokenId uint256 소각할 토큰의 ID
     */
    function _burn(address owner, uint256 tokenId) internal {
        require(ownerOf(tokenId) == owner, "ERC721: burn of token that is not own");

        _clearApproval(tokenId);

        _ownedTokensCount[owner].decrement();
        _tokenOwner[tokenId] = address(0);

        emit Transfer(owner, address(0), tokenId);
    }

    /**
     * @dev 특정 토큰을 소각하기 위한 내부 함수.
     * Reverts if the token does not exist.
     * @param tokenId uint256 소각할 토큰의 ID
     */
    function _burn(uint256 tokenId) internal {
        _burn(ownerOf(tokenId), tokenId);
    }

    /**
     * @dev 주어진 토큰 ID의 소유권을 다른 주소로 전송하기 위한 내부 함수.
     * transferFrom과 달리, msg.sender에 제한이 없습니다.
     * @param from 토큰의 현재 소유자
     * @param to 주어진 토큰 ID의 소유권을 받고자 하는 주소
     * @param tokenId uint256 전송될 토큰의 ID
     */
    function _transferFrom(address from, address to, uint256 tokenId) internal {
        require(ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
        require(to != address(0), "ERC721: transfer to the zero address");

        _clearApproval(tokenId);

        _ownedTokensCount[from].decrement();
        _ownedTokensCount[to].increment();

        _tokenOwner[tokenId] = to;

        emit Transfer(from, to, tokenId);
    }

    /**
     * @dev 목표 주소에서 `onERC721Received`를 호출할 내부 함수.
     * 대상 주소가 컨트랙트가 아닌 경우 호출이 실행되지 않습니다.
     *
     * 이 기능은 더 이상 사용되지 않습니다.
     * @param from 주어진 토큰 ID의 이전 소유자를 나타내는 주소
     * @param to 토큰을 받을 목표 주소
     * @param tokenId uint256 전송될 토큰의 ID
     * @param _data bytes 호출과 함께 전송할 추가 데이터
     * @return bool 호출이 예상한 값(magic value)을 반환했는지 여부
     */
    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)
        internal returns (bool)
    {
        if (!to.isContract()) {
            return true;
        }

        bytes4 retval = IERC721Receiver(to).onERC721Received(msg.sender, from, tokenId, _data);
        return (retval == _ERC721_RECEIVED);
    }

    /**
     * @dev 주어진 토큰 ID의 현재 승인을 지우는 개인 함수.
     * @param tokenId uint256 전송할 토큰의 ID
     */
    function _clearApproval(uint256 tokenId) private {
        if (_tokenApprovals[tokenId] != address(0)) {
            _tokenApprovals[tokenId] = address(0);
        }
    }
}

contract MyERC721Card is ERC721{

    struct Card {
        string  name;  // 카드의 이름
        uint256 level; // 카드의 레벨
    }

    Card[] public cards; // 첫 아이템의 인덱스는 0입니다
    address public owner;

    constructor () public {
        owner = msg.sender; // 새 카드를 생성할 수 있는 MyERC721Card 컨트랙트의 소유자
    }

    function mintCard(string memory name, address account) public {
        require(owner == msg.sender); // 소유자만이 카드를 생성할 수 있습니다
        uint256 cardId = cards.length; // 유일한 카드 ID
        cards.push(Card(name, 1));
        _mint(account, cardId); // 새 카드를 발행
    }

}
```

`MyERC721Card.sol`은 하나의 인터페이스(`IERC165`), 세 라이브러리(`Address`, `SafeMath` 그리고 `Counters`) 그리고 네 컨트랙트(`ERC165`, `IERC721`, `IERC721Receiver` 그리고 `MyERC721Card`)로 구성됩니다.

* `IERC165` 인터페이스는 [ERC-165 스펙](https://eips.ethereum.org/EIPS/eip-165)에 명시된 인터페이스를 정의합니다.
* `Address` 라이브러리는 `account`가 컨트랙트인지 여부를 테스트하는 `isContract` 메소드를 정의합니다.
* `SafeMath` library defines wrappers over Solidity's arithmetic operations with added overflow checks for safe calculation of `uint256` type of Solidity.
* `Counters` 라이브러리는 오직 1만큼만 증가하거나 감소할 수 있는 카운터를 정의합니다. 이는 ERC721 ID를 발행할 때 원소의 개수를 추적하는 것에 사용됩니다.
* `ERC165`는 `IERC165` 인터페이스를 구현합니다.
* `IERC721`는 ERC-165를 포함한 [ERC-721 스펙](https://eips.ethereum.org/EIPS/eip-721)에 명시된 인터페이스를 정의합니다.
* `IERC721Receiver`는 `MyERC721Card` 컨트랙트에 사용된 `onERC721Received`를 정의합니다.
* `ERC721`는 `IERC721` 및 `ERC165` 인터페이스를 구현합니다.
* `MyERC721Card`는 `ERC721`을 사용한, 이름과 레벨을 포함한 카드 타입의 대체 불가능한 토큰을 구현합니다. `MyERC721Card` 컨트랙트의 소유자만이 새로운 카드를 발행할 수 있습니다.

## 1.2 Take a look at important methods <a href="#id-1-2-take-a-look-at-important-methods" id="id-1-2-take-a-look-at-important-methods"></a>

Let's take a look at some important methods in detail.

### (1) `constructor` of ERC721 and `_INTERFACE_ID_ERC721` <a href="#id-1-constructor-of-erc721-and-_interface_id_erc721" id="id-1-constructor-of-erc721-and-_interface_id_erc721"></a>

`constructor`는 아래의 ERC-721 인터페이스로부터 구해진 4바이트 해시인 `_INTERFACE_ID_ERC721`을 등록합니다.

```
    /*
     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231
     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e
     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3
     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc
     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465
     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c
     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd
     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e
     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde
     *
     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^
     *        0xa22cb465 ^ 0xe985e9c ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd
     */
    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;

    constructor () public {
        // ERC165를 통한 ERC721의 확인을 위한 지원 인터페이스 등록
        _registerInterface(_INTERFACE_ID_ERC721);
    }
```

등록 후, `_INTERFACE_ID_ERC721`에 대해 호출될 때 `supportsInterface`인 ERC-721 및 ERC-165의 인터페이스는 `true`를 반환하고, 이 컨트랙트가 ERC-721 인터페이스를 구현하고 있음을 알려줍니다.

### (2) `function balanceOf(address owner) public view returns (uint256 balance);` <a href="#id-2-function-balanceof-address-owner-public-view-returns-uint256-balance" id="id-2-function-balanceof-address-owner-public-view-returns-uint256-balance"></a>

`balanceOf`는 ERC-721의 필수 메소드입니다. `balanceOf`는 `owner`의 계정에 들어 있는 NFT의 개수를 반환합니다.

```
    function balanceOf(address owner) public view returns (uint256) {
        require(owner != address(0), "ERC721: balance query for the zero address");

        return _ownedTokensCount[owner].current();
    }
```

`balanceOf`는 단지 `owner`가 `_ownedTokensCount`에서 유지하는 `Counter` 객체로부터 현재 카운트를 반환합니다.

```
    // 소유자로부터 소유한 토큰의 개수로의 매핑
    mapping (address => Counters.Counter) private _ownedTokensCount;
```

### (3) `safeTransferFrom` and `transferFrom` <a href="#id-3-safetransferfrom-and-transferfrom" id="id-3-safetransferfrom-and-transferfrom"></a>

이 함수는 주어진 토큰 ID의 소유권을 다른 주소로 넘겨줍니다. ERC-721로부터 요구되는 두 개의 `safeTransferFrom` 메소드가 있습니다. 하나는 `data`가 있으며, 다른 하나는 `data`가 없습니다. `data`가 없는 메소드는 `data`를 `""`으로 설정한다는 점을 제외하면, 두 메소드 모두 동일하게 작동합니다. `safeTransferFrom`는 아래의 더 많은 검사와 함께 `transferFrom`를 호출하며, `safeTransferFrom`는 또 다른 ERC-721의 필수 메소드인 `transferFrom`보다 선호됩니다.

```
    function safeTransferFrom(address from, address to, uint256 tokenId) public {
        safeTransferFrom(from, to, tokenId, "");
    }

    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public {
        transferFrom(from, to, tokenId);
        require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
    }

    function transferFrom(address from, address to, uint256 tokenId) public {
        //solhint-disable-next-line max-line-length
        require(_isApprovedOrOwner(msg.sender, tokenId), "ERC721: transfer caller is not owner nor approved");

        _transferFrom(from, to, tokenId);
    }
```

`safeTransferFrom`은 `to` 주소가 토큰을 받을 수 있는지를 검사합니다. `_checkOnERC721Received`는 검증 로직을 가집니다. 만일 `to` 주소가 컨트랙트라면 ERC-721의 `onERC721Received` 인터페이스를 구현해야 하며, 아래와 같이 ERC-721 토큰을 받기 위해 올바른 4바이트 해시를 반환해야 합니다.

```
    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)
        internal returns (bool)
    {
        if (!to.isContract()) {
            return true;
        }

        bytes4 retval = IERC721Receiver(to).onERC721Received(msg.sender, from, tokenId, _data);
        return (retval == _ERC721_RECEIVED);
    }
```

`_transferFrom`은 아래와 같이 주어진 `tokenId`의 소유권을 실제로 이전합니다.

```
    function _transferFrom(address from, address to, uint256 tokenId) internal {
        require(ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
        require(to != address(0), "ERC721: transfer to the zero address");

        _clearApproval(tokenId);

        _ownedTokensCount[from].decrement();
        _ownedTokensCount[to].increment();

        _tokenOwner[tokenId] = to;

        emit Transfer(from, to, tokenId);
    }
```

### (4) `function _mint(address to, uint256 tokenId) internal` <a href="#id-4-function-_mint-address-to-uint256-tokenid-internal" id="id-4-function-_mint-address-to-uint256-tokenid-internal"></a>

`_mint`는 ERC-721의 일부가 아닙니다. 그러나 새로운 ERC-721 토큰을 생성할 방법이 필요하며, 이 구현체에서 새 토큰을 생성하기 위해 아래와 같은 `_mint`가 필요합니다.

```
    function _mint(address to, uint256 tokenId) internal {
        require(to != address(0), "ERC721: mint to the zero address");
        require(!_exists(tokenId), "ERC721: token already minted");

        _tokenOwner[tokenId] = to;
        _ownedTokensCount[to].increment();

        emit Transfer(address(0), to, tokenId);
    }
```

`_mint` is an internal method and can be invoked inside of this contract. `MyERC721Card.sol`에서 `_mint`는 오직 `MyERC721Card`의 `mintCard` 메소드에서만 호출됩니다. 스마트 컨트랙트의 소유자만이 `mintCard`를 호출할 수 있습니다.

```
    function mintCard(string name, address account) public {
        require(owner == msg.sender); // Only the Owner can create Items
        uint256 cardId = cards.length; // Unique card ID
        cards.push(Card(name, 1));
        _mint(account, cardId); // Mint a new card
    }
```


# 2. Deploying Smart Contract

You can use Remix Online IDE or use truffle to deploy above `MyERC721Card` smart contract.

## 2.1 Deploying smart contract using Remix Online IDE <a href="#id-2-1-deploying-smart-contract-using-klaytn-ide" id="id-2-1-deploying-smart-contract-using-klaytn-ide"></a>

* Please visit [Klaytn Plugin for Remix](https://ide.klaytn.foundation) and create a `MyERC721Card` contract. The complete source code is given at [Writing ERC-721 Smart Contract](/content/smart-contract/sample-contracts/erc-721/1-erc721).
* Create an account to deploy the contract with.
  * If you do not have an account yet, create one at <https://baobab.wallet.klaytn.foundation/create> or <https://toolkit.klaytn.foundation/account/accountKeyLegacy>.
  * Get some test KLAY from the faucet - <https://baobab.wallet.klaytn.foundation/faucet>
* 아래와 같이 `MyERC721Card.sol`를 배포합시다.

![ERC721-1-배포](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-b2f6d59bc9e7d8ef1cadbbfe9de5cc3027104562%2Ferc721-1-deploy.png?alt=media\&token=01f848a7-2a21-4f70-87a8-0a32357a9e20)

이제 `MyERC721`가 활성화되었습니다! ERC-721을 호환하는 대체 불가능한 토큰인 카드를 발행하고 전송할 수 있습니다.

아래와 같이 두 카드, 즉 `King`과 `Queen` 카드를 `0x2645BA5Be42FfEe907ca8e9d88f6Ee6dAd8c1410` 계정에 대해 발행해봅시다.

![ERC721-2-발행-king](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-6e2b24ce83b8c51c3feb2d0fe836c2f9fc2d0ba3%2Ferc721-2-mint-king.png?alt=media\&token=baeb8ef5-5e31-4dce-bd3f-925602928ec9) ![ERC721-3-발행-queen](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-af70b379e08b5691eb27e048c6d352fa293adbae%2Ferc721-3-mint-queen.png?alt=media\&token=cf46206f-1a11-4a57-ac7e-ee827cbdf049)

이제 우리는 두 카드를 발행했고, 이들 `MyERC721Card` 대체 불가능한 토큰의 상태를 확인해봅시다.

![ERC721-4-카드-상태](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-a6864c942abf12ee2c4c344473c884f5033922a5%2Ferc721-4-cards-status.png?alt=media\&token=a83b8790-fc38-457f-a007-69dfc5de096a)

* `balanceOf`는 계정 `0x2645BA5Be42FfEe907ca8e9d88f6Ee6dAd8c1410`가 두 카드를 가졌음을 보여줍니다.
* 파라미터 `1`인 `cards`는 토큰 ID가 `1`인 `MyERC721Card`가 레벨 1의 `Queen`임을 보여줍니다.
* 파라미터 `0`인 `ownerOf`는 토큰 ID가 `0`인 `MyERC721Card`의 소유자가 `0x2645BA5Be42FfEe907ca8e9d88f6Ee6dAd8c1410`임을 보여줍니다.

## 2.2 Deploying smart contract using truffle <a href="#id-2-2-deploying-smart-contract-using-truffle" id="id-2-2-deploying-smart-contract-using-truffle"></a>

You should have installed [node.js](https://nodejs.org/) in your environment. Please take a look at [Installing Node.js via package manager](https://nodejs.org/en/download/package-manager/) to install node.js using package manager in various environment.

```
$ mkdir klaytn
$ cd klaytn
$ npm init # initialize npm at the erc20token directory
$ npm install truffle@4.1.15
$ npm install caver-js@latest # installing caver-js
$ ln -s node_modules/truffle/build/cli.bundled.js truffle
$ export PATH=`pwd`:$PATH
```

이제 스마트 컨트랙트를 배포하는 데 필요한 truffle 및 caver-js를 설치했습니다.

`truffle`과 스마트 컨트랙트 `MyERC721Card.sol`을 준비합시다.

```
$ mkdir myerc721
$ cd myerc721
$ truffle init
```

Now you will have following directory structures.

```
.
├── contracts
│   ├── Migrations.sol
├── migrations
│   └── 1_initial_migration.js
└── truffle-config.js
```

`MyERC721Card.sol`를 작성하고 `contracts` 디렉토리에 위치시킨 후, 디렉토리 구조는 다음과 같을 것입니다.

Now you will have following directory structures.

```
.
├── contracts
│   ├── Migrations.sol
│   └── MyERC721Card.sol
├── migrations
│   └── 1_initial_migration.js
└── truffle-config.js
```

또한, `MyERC721Card` 컨트랙트를 배포하기 위해 아래와 같이 `1_initial_migration.js`를 편집하세요.

```javascript
const Migrations = artifacts.require("./Migrations.sol");
const MyERC721Card = artifacts.require("./MyERC721Card.sol");
module.exports = function(deployer) {
  deployer.deploy(Migrations);
  deployer.deploy(MyERC721Card)
};
```

또한 Klaytn 네트워크에 스마트 컨트랙트를 배포하기 위해 `truffle-config.js`를 구성해야 합니다. 이는 [트러플을 사용하여 스마트 컨트랙트 배포 ](/content/getting-started/quick-start/deploy-a-smart-contract#deploying-a-smart-contract-using-truffle)에 설명된 순서와 동일합니다.

```
// truffle-config.js
module.exports = {
    networks: {
        baobab: {
            host: '127.0.0.1',
            port: 8551,
            from: '0xabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd', // enter your account address
            network_id: '1001', // Baobab network id
            gas: 20000000, // transaction gas limit
            gasPrice: 250000000000, // gasPrice of Baobab is 250 ston
        },
    },
    compilers: {
      solc: {
        version: "0.5.12"    // Specify compiler's version to 0.5.12
      }
  }
};
```

이제 모두 준비되었습니다. 다음 명령을 사용해 `MyERC721Card.sol`을 배포합시다.

```
$ truffle deploy --network baobab --reset
Compiling ./contracts/MyERC721Card.sol...
Writing artifacts to ./build/contracts

Using network 'baobab'.

Running migration: 1_initial_migration.js
  Replacing Migrations...
  ... 0x5a947f076f4570dff8ff18b1ae3557e27dd69c92ce38a3c97fad8f5355914066
  Migrations: 0x0d737e9865e5fc4c1ff53744fd2c13c52a44b9bc
  Deploying MyERC721Card...
  ... 0x1571e80552dab1d67260e8914e06d9b16ccae16fb698c750f6a09aab12517bc1
  MyERC721Card: 0xc3d282926871c505f334d0f2c85ad52758347831
Saving successful migration to network...
  ... 0x5b984b3f79c425d80470a96d5badb857fc05e7f31d94423044ae3119c639aa77
Saving artifacts...
```

`MyERC721Card`를 배포하기 위한 트랜잭션 해시는 `0x1571e80552dab1d67260e8914e06d9b16ccae16fb698c750f6a09aab12517bc1`이며 `MyERC721Card`의 주소는 `0xc3d282926871c505f334d0f2c85ad52758347831`입니다.


# 테스트 가이드

이 장에서는 스마트 컨트랙트를 테스트하는 방법을 소개합니다. 블록체인의 트랜잭션은 되돌릴 수 없으므로 스마트 컨트랙트를 배포하기 전에 테스트하는 것이 매우 중요합니다.

## 트러플(Truffle)로 테스트하기 <a href="#testing-with-truffle" id="testing-with-truffle"></a>

트러플은 자동 테스트 프레임워크를 제공합니다. 이 프레임워크를 사용하여 간단하고 관리 가능한 테스트를 작성할 수 있는 방법이 두 가지 있습니다.

* `Javascript` 및 `TypeScript`를 이용하여 블록체인 외부에서 컨트랙트를 실행하는 애플리케이션처럼 작성
* `Solidity`를 활용하여 컨트랙트 함수를 직접 호출

### 1) 시작하기 <a href="#id-1-getting-started" id="id-1-getting-started"></a>

We will follow the [Deployment Guide using Truffle](/content/smart-contract/deploy-guide#truffle) to create a contract and deploy it. 다만 배포하기 전에 스마트 컨트랙트 테스트를 위해 값 설정 함수 `setGreet` 함수를 추가합니다. 소스 코드는 아래와 같습니다.

**참고:** 테스트를 위해 스마트 컨트랙트의 일부를 수정하였습니다.

아래는 KlaytnGreeting 컨트랙트의 소스 코드입니다.

```
pragma solidity 0.5.6;
contract Mortal {
    /* 주소 타입의 소유자(owner) 변수 정의 */
    address payable owner;
    /* 이 함수는 초기화 시점에 실행되어 컨트랙트 소유자를 설정합니다 */
    constructor () public { owner = msg.sender; }
    /* 컨트랙트에서 자금을 회수하는 함수 */
    function kill() public payable { if (msg.sender == owner) selfdestruct(owner); }
}

contract KlaytnGreeter is Mortal {
    /* 문자열 타입의 변수 greeting 정의 */
    string greeting;
    /* 이 함수는 컨트랙트가 실행될 때 작동합니다 */
    constructor (string memory _greeting) public {
        greeting = _greeting;
    }
    /* 주(Main) 함수 */
    function greet() public view returns (string memory) {
        return greeting;
    }
}

    /* 테스트를 위해 새로 추가된 함수입니다 */
    function setGreet(string memory _greeting) public {
        // 소유자(owner)만 greeting 메세지를 수정할 수 있습니다
        require(msg.sender == owner, "Only owner is allowed.");
        greeting = _greeting;
    }
}
```

1. `greet()` 함수가 "Hello, Klaytn"이라는 메세지를 잘 출력하는지, 2) `setGreet()` 함수가 새로 설정된 greeting 메세지를 잘 출력하고 소유자가 아닌 계정이 greeting을 업데이트하려고 할 때 revert를 하는지 테스트해보겠습니다.

먼저 일반적인 어설션(assertions)을 위해 Chai 어설션 라이브러리를 설치하고 (또는 사용하고 있는 다른 어설션 라이브러리도 괜찮습니다), 스마트 컨트랙트 어설션을 위해 truffle-assertions 라이브러리를 설치합니다.

```
npm install --save-dev chai truffle-assertions
```

### 2) 솔리디티로 테스트 작성하기 <a href="#id-2-writing-test-in-solidity" id="id-2-writing-test-in-solidity"></a>

솔리디티로 테스트하는 것은 자바스크립트로 테스트하는 것보다 조금 더 직관적일 수 있습니다. 솔리디티 테스트 컨트랙트는 자바스크립트 테스트와 함께 .sol 파일로 제공됩니다.

`test` 폴더에 `TestKlaytnGreeting.sol`이란 이름의 파일을 생성합니다. 트러플 제품군은 테스트를 위한 헬퍼(helper) 라이브러리를 제공하므로, 이들을 불러옵니다. 솔리디티 테스트 예시를 살펴봅시다.

```
pragma solidity ^0.5.6;

import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../contracts/HashMarket.sol";
```

* Assert : `Assert.equals()`, `Assert.greaterThan()` 등과 같은 다양한 테스트 함수에 액세스할 수 있도록 합니다.
* DeployedAddresses : 컨트랙트를 변경할 때마다, 반드시 새 주소로 재배포해야 합니다. 이 라이브러리를 통해 배포된 컨트랙트 주소를 얻을 수 있습니다.

이제 테스트 코드를 작성해 봅시다.

```
pragma solidity ^0.5.6;

import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../contracts/KlaytnGreeter.sol";

contract TestKlaytnGreeter {

    function testGreetingMessage() public {
        // DeployedAddresses.KlaytnGreeter()는 컨트랙트 주소를 다룹니다.
        KlaytnGreeter greeter = KlaytnGreeter(DeployedAddresses.KlaytnGreeter());

        string memory expectedGreet = "Hello Klaytn";

        string memory greet = greeter.greet();

        Assert.equal(greet, expectedGreet, "greeting message should match");
    }
}
```

Run your Solidity test code.

```
$ truffle test
# Output
Using network 'development'.


Compiling your contracts...
===========================
> Compiling ./test/TestKlaytnGreeter.sol



  TestKlaytnGreeter
    1) testGreetingMessage

    Events emitted during test:
    ---------------------------


    ---------------------------


  0 passing (5s)
  1 failing

  1) TestKlaytnGreeter
       testGreetingMessage:
     Error: greeting message should match (Tested: Hello, Klaytn, Against: Hello Klaytn)
      at result.logs.forEach.log (/Users/jieunkim/.nvm/versions/node/v10.16.0/lib/node_modules/truffle/build/webpack:/packages/core/lib/testing/soliditytest.js:71:1)
      at Array.forEach (<anonymous>)
      at processResult (/Users/jieunkim/.nvm/versions/node/v10.16.0/lib/node_modules/truffle/build/webpack:/packages/core/lib/testing/soliditytest.js:69:1)
      at process._tickCallback (internal/process/next_tick.js:68:7)
```

앗, 실패했습니다. 오류 메시지 `Error: greeting message should match (Tested: Hello, Klaytn, Against: Hello Klaytn)`를 확인해봅시다. I can notice the missed `',(comma)'` at *string memory expectedGreet = "Hello Klaytn"*.\
Fix the code and run the test again.

```
$ truffle test
# Output
Using network 'development'.


Compiling your contracts...
===========================
> Compiling ./test/TestKlaytnGreeter.sol



  TestKlaytnGreeter
    ✓ testGreetingMessage (58ms)


  1 passing (5s)
```

축하합니다! 테스트가 통과되었습니다.

### 3) 자바스크립트로 테스트 작성하기 <a href="#id-3-writing-test-in-javascript" id="id-3-writing-test-in-javascript"></a>

트러플은 자바스크립트 테스트를 위한 견고한 프레임워크를 제공하기 위해 [Mocha](https://mochajs.org/) 테스트 프레임워크 및 [Chai](https://www.chaijs.com/) 어설션 라이브러리를 사용합니다. 자바스크립트 테스트는 더 많은 유연성을 제공하며 더 복잡한 테스트를 작성할 수 있게 합니다.

Let's create a file and name it `0_KlaytnGreeting.js` under `test` directory.\
The test code is:

```javascript
// KlaytnGreeter 컨트랙트와 직접 상호작용
const KlaytnGreeter = artifacts.require("./KlaytnGreeter.sol");
const truffleAssert = require('truffle-assertions');

contract("KlaytnGreeter", async(accounts) => {
    // 컨트랙트 인스턴스를 상위 레벨에 저장해
    // 모든 함수에서 접근할 수 있도록 합니다.
    var klaytnGreeterInstance;
    var owner = accounts[0];
    var greetMsg = "Hello, Klaytn";

    // 각 테스트가 진행되기 전에 실행됩니다.
    before(async function() {
        // set contract instance into a variable
        klaytnGreeterInstance = await KlaytnGreeter.new(greetMsg, {from:owner});
    })

    it("#1 check Greeting message", async function() {
        // set the expected greeting message
        var expectedGreeting = greetMsg;
        var greet= await klaytnGreeterInstance.greet();
        assert.equal(expectedGreeting, greet, "greeting message should match");

    })

    it("#2 update greeting message.", async function() {
        var newGreeting = "Hi, Klaytn";

        await klaytnGreeterInstance.setGreet(newGreeting, { from:owner });
        var greet = await klaytnGreeterInstance.greet();
        assert.equal(newGreeting, greet, "greeting message should match");
    });

    it("#3 [Failure test] Only owner can change greeting.", async function() {
        var fakeOwner = accounts[1];        
        await truffleAssert.fails(klaytnGreeterInstance.setGreet(greetMsg, { from:fakeOwner }));
    });
});
```

만일 `Mocha` 유닛 테스트에 익숙하지 않다면, [Mocha 문서](https://mochajs.org/#getting-started)를 참조하시길 바랍니다.

* Use `contract()` instead of `describe()`\
  Structurally, the Truffle test code shouldn't be much different from the usual test code of Mocha. 테스트에는 Mocha가 자동화된 테스트임을 인지할 수 있도록 하는 코드가 포함되어야 합니다. The difference between Mocha and Truffle test is the contract() function.\ **NOTE** the use of the `contract()` function, and the `accounts` array for specifying available Klaytn accounts.
* Contract abstractions within your tests\
  Since Truffle has no way of detecting which contract you'll need to interact with during test, you should specify the contract explicitly. 이를 수행하는 한 방법은 `artifacts.require()` 메소드를 사용하는 것입니다.
* `it` syntax\
  This represents each test case with description. 테스트 실행 시 콘솔에 설명이 출력됩니다.
* `truffle-assertion` library\
  This library allows you to easily test reverts or other failures by offering the `truffleAssert.reverts()` and `truffleAssert.fails()` functions.

출력은 다음과 같아야 합니다:

```
Using network 'development'.


Compiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.



  Contract: KlaytnGreeter
    ✓ #1 check Greeting message
    ✓ #2 update greeting message. (46ms)
    ✓ #3 [Failure test] Only owner can change greeting.


  3 passing (158ms)
```

Congratulations! Your test has passed.

### 4) 테스트 지정하기 <a href="#id-4-specifying-test" id="id-4-specifying-test"></a>

실행할 테스트 파일을 선택할 수 있습니다.

```
truffle test ./test/0_KlaytnGreeting.js
```

자세한 내용은 [Truffle testing](https://www.trufflesuite.com/docs/truffle/testing/testing-your-contracts) 및 [Truffle commands](https://www.trufflesuite.com/docs/truffle/reference/truffle-commands#test)을 참조하시길 바랍니다.


# 배포 가이드

클레이튼에 스마트 컨트랙트를 배포하는 방법에는 여러 가지가 있습니다. 이 문서는 다양한 도구를 사용하여 샘플 컨트랙트를 배포하기 위한 단계별 가이드를 제공합니다. 트랜잭션 수수료를 지불하기에 충분한 KLAY가 있는 Klaytn 계정이 있다고 가정합니다. 계정을 만들려면 [Klaytn Wallet](/content/dapp/developer-tools/getting-started/klaytn-wallet)을 참조하세요.

## Remix Online IDE <a href="#remix-ide" id="remix-ide"></a>

Open your internet browser and go to [Klaytn Plugin for Remix](https://ide.klaytn.foundation).

* 새 파일을 추가하세요.

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-52fb0a0543e8dc8eec6f6923a9345eb63c2efa9b%2F01_deployment_ide.png?alt=media)

* 다음 코드(또는 배포하고자 하는 아무 코드)를 복사해 붙여넣습니다. 이 코드는 Mortal과 KlaytnGreeter라는 두 컨트랙트로, 간단히 "Hello World!"를 실행할 수 있습니다.

```
pragma solidity 0.5.12;

contract Mortal {
    /* Define variable owner of the type address */
    address payable owner;
    /* This function is executed at initialization and sets the owner of the contract */
    constructor () public { owner = msg.sender; }
    /* Function to recover the funds on the contract */
    function kill() public payable { if (msg.sender == owner) selfdestruct(owner); }
}

contract KlaytnGreeter is Mortal {
    /* Define variable greeting of the type string */
    string greeting;
    /* This runs when the contract is executed */
    constructor (string memory _greeting) public {
        greeting = _greeting;
    }
    /* Main function */
    function greet() public view returns (string memory) {
        return greeting;
    }
}
```

* 아이콘 패널에서 Compiler를 선택해주세요. 그리고 원하는 EVM 환경을 선택합니다. 클레이튼 네트워크의 경우 Baobab(테스트넷)과 Cypress(메인넷) 사이에서 선택할 수 있습니다. Click `Compile` when the sample code is ready to be complied before actual deployment.

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-a5346e203bb55e2598f94776a68109e96e451f8e%2F02_deployment_compile.png?alt=media)

* 이제 컨트랙트를 배포할 수 있습니다. 아이콘 패널에서 클레이튼 로고를 선택해주세요. `Account` 옆의 더하기 버튼을 눌러 계정을 가져올 수 있습니다. Make sure that the account has sufficient KLAY to pay for the transaction of deploying the smart contracts required.

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-728230acc907bc8de68f994fc6b3cc10ad42aa71%2F05_deployment_account.png?alt=media)

* 보낼 가스 한도 및 값을 설정하세요.
  * 보다 복잡한 컨트랙트를 배포하는 경우 가스 한도를 더 높게 설정해야 할 수 있습니다. 이 예시에서는 그대로 두어도 됩니다.
  * 배포 시 컨트랙트에 `KLAY`를 보내고 싶지 않다면 `값(Value)`을 0으로 설정하세요.
* "Hello World!"를 생성자 함수의 인자로 입력하고 `배포(Deploy)` 버튼을 클릭하세요.

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-08e6419bc97e0d3f068ec1231be3b73b87056f57%2F03_deployment_hello.png?alt=media)

* 컨트랙트가 성공적으로 배포되었다면 터미널에 상응하는 트랜잭션 receipt와 자세한 결과값을 볼 수 있습니다.
* 함수 버튼을 클릭하여 컨트랙트와 상호작용할 수 있습니다. 함수들은 다양한 색으로 표시됩니다. 솔리디티의 `constant` 또는 `pure` 함수는 파란색 버튼으로 표시되며(예시에서 `greet`), 새로운 트랜잭션을 생성하지 않기 때문에 가스비가 들지 않습니다. 빨간색 버튼(예시에서 `kill`)은 `payable` 함수로서, 블록체인의 상태를 변경하고 가스를 소진하며 KLAY를 받을 수 있습니다. 오렌지 버튼은 컨트랙트 상태를 변경시키지만 KLAY를 받을 수는 없는 `non-payable` 함수를 나타냅니다.

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-e247f93f3a8bb193f2bd54524a91e358e887af49%2F06_deployment_functions.png?alt=media)

자세한 내용은 [링크](https://github.com/klaytn/klaytn-docs-ko/blob/main/docs/toolkit/klaytn-ide.md)를 참고해주세요.

## Truffle <a href="#truffle" id="truffle"></a>

트러플은 스마트 컨트랙트 배포 및 실행에 가장 널리 사용되는 프레임워크입니다.

* 다음 명령을 통해 설치하세요.

```
$ sudo npm install -g truffle
```

* 프로젝트 디렉토리를 설정하고, `truffle-hdwallet-provider-klaytn`를 설치하세요.

```
$ mkdir hello-klaytn
$ cd hello-klaytn
$ truffle init
$ npm install truffle-hdwallet-provider-klaytn
```

* `/contracts` 디렉토리 하에 `KlaytnGreeter.sol`를 생성하고 다음 코드를 복사합니다.

```
pragma solidity 0.5.6;
contract Mortal {
    /* 주소 타입의 소유자(owner) 변수 정의 */
    address payable owner;
    /* 이 함수는 초기화 시점에 실행되어 컨트랙트 소유자를 설정합니다 */
    constructor () public { owner = msg.sender; }
    /* 컨트랙트에서 자금을 회수하는 함수 */
    function kill() public payable { if (msg.sender == owner) selfdestruct(owner); }
}

contract KlaytnGreeter is Mortal {
    /* 문자열 타입의 변수 greeting 정의 */
    string greeting;
    /* 이 함수는 컨트랙트가 실행될 때 작동합니다 */
    constructor (string memory _greeting) public {
        greeting = _greeting;
    }
    /* 주(Main) 함수 */
    function greet() public view returns (string memory) {
        return greeting;
    }
}
```

* `/migrations/1_initial_migration.js`를 다음과 같이 수정합니다.

```
const Migrations = artifacts.require("./Migrations.sol");
const KlaytnGreeter = artifacts.require("./KlaytnGreeter.sol");
module.exports = function(deployer) {
  deployer.deploy(Migrations);
  deployer.deploy(KlaytnGreeter, 'Hello, Klaytn');
};
```

* Set `truffle-config.js` as below. 컨트랙트를 배포할 충분한 `KLAY`를 가진 계정의 개인키를 입력하세요.

```
const HDWalletProvider = require("truffle-hdwallet-provider-klaytn");

const privateKey = "0x3de..." 
 
XPath: /pre[6]/code
```

*참고*: 이 예제는 상업용으로 권장되지 않습니다. 개인키를 다룰 때 많은 주의를 기울이세요.

* Klaytn 테스트넷에 배포.

```
$ truffle deploy --network testnet
```

* Klaytn 메인넷에 배포.

```
$ truffle deploy --network mainnet
```

자세한 내용은 이 [링크](/content/smart-contract/ide-and-tools/truffle)를 참조하세요.

## VVISP <a href="#vvisp" id="vvisp"></a>

vvisp은 스마트 컨트랙트 개발을 위해 HEACHI LABS에서 제공하는 사용하기 쉬운 cli 도구/프레임워크입니다. 단일 명령만으로 환경을 쉽게 설정하고, Klaytn 스마트 컨트랙트를 배포 및 실행할 수 있습니다. 자세한 내용을 위해 다음 링크를 참조하세요.

* <https://henesis.gitbook.io/vvisp/deploying-smart-contracts>

## solc & caver-js <a href="#solc-caver-js" id="solc-caver-js"></a>

컨트랙트를 배포하는 또 다른 방법은 solc로 컨트랙트를 수동으로 컴파일하고 caver-js로 컨트랙트를 배포하는 것입니다.

* `KlaytnGreeter.sol`를 생성하고 다음 코드를 작성하세요.

```
pragma solidity 0.5.6;

contract Mortal {
    /* Define variable owner of the type address */
    address payable owner;
    /* This function is executed at initialization and sets the owner of the contract */
    constructor () public { owner = msg.sender; }
    /* Function to recover the funds on the contract */
    function kill() public payable { if (msg.sender == owner) selfdestruct(owner); }
}

contract KlaytnGreeter is Mortal {
    /* Define variable greeting of the type string */
    string greeting;
    /* This runs when the contract is executed */
    constructor (string memory _greeting) public {
        greeting = _greeting;
    }
    /* Main function */
    function greet() public view returns (string memory) {
        return greeting;
    }
}
```

* solc 0.5.6을 설치하세요.

```
$ sudo npm install -g solc@0.5.6
```

* 컨트랙트를 컴파일하세요.

```
$ solcjs KlaytnGreeter.sol --bin
```

* caver-js를 설치하세요.

```
$ npm install caver-js.
```

* 같은 디렉토리에 다음 코드의 `deploy.js`를 생성하세요.

```
const Caver = require("caver-js");
const caver = new Caver("https://public-en-baobab.klaytn.net")

const walletInstance = caver.klay.accounts.privateKeyToAccount(
  '0x3de0c9...' // enter your private key to deploy contract with
);
caver.klay.accounts.wallet.add(walletInstance);

const fs = require('fs')
const bytecode = fs.readFileSync('./KlaytnGreeter_sol_KlaytnGreeter.bin') // compiled output

const constructorType = ['string']  // enter appropriate constructor type
const constructorValue = ['Hello, Klaytn!']

const params = caver.klay.abi.encodeParameters(constructorType, constructorValue);

caver.klay.sendTransaction({
  from: caver.klay.accounts.wallet[0].address,
  gas: "50000000",
  data: bytecode.toString() + params.substring(2, params.length)
})
.once("receipt", receipt => {
  console.log(receipt)
})
.once("error", error => {
  console.log(error);
})
```

*NOTE*: This example is not recommended for production use. Be very careful when dealing with private keys.

* node 환경을 사용해 컨트랙트를 배포하세요.

```
$ node deploy.js
```


# 클레이튼 호환 토큰

Klaytn 호환 토큰(KCT, Klaytn Compatible Token)는 특정 기술 스펙을 구현한 특별한 타입의 스마트 컨트랙트입니다. Klaytn에서 토큰을 발행하려는 모든 사람들은 스펙을 따라야 합니다.

Token standards are defined in Klaytn such as [KIP-7](https://kips.klaytn.foundation/KIPs/kip-7) and [KIP-17](https://kips.klaytn.foundation/KIPs/kip-17).

다른 형태의 KCT도 일련의 기술적 요구사항에 맞추어 정의될 수 있습니다. 혹시 다른 토큰 표준이 필요하다면 [Klaytn Improvement Proposal](https://github.com/klaytn/KIPs)을 방문하셔서 새로운 토큰 표준을 제안하십시오.

## 대체 가능 토큰 표준 (KIP-7) <a href="#fungible-token-standard-kip-7" id="fungible-token-standard-kip-7"></a>

대체 가능한 토큰은 균등성과 가분(可分)성을 가진 토큰입니다. 각 토큰 단위는 동일한 가치를 가지므로 모든 가용 토큰은 서로 호환됩니다. 모든 달러 지폐가 동일하게 1달러 가치인 것과 같습니다. 대부분의 경우 대체 가능성은 암호 화폐에 필수적인 기능이기 때문에, 블록체인 토큰 중 많은 비율이 대체 가능한 토큰입니다.

이러한 특성을 스마트 컨트랙트에 담기 위해 KIP-7 토큰 표준을 사용할 수 있습니다. KIP-7 호환 토큰은 다음에 소개할 인터페이스를 사용합니다. Please note that [KIP-13](https://kips.klaytn.foundation/KIPs/kip-13) must be implemented together. For wallet applications, [wallet interface](https://kips.klaytn.foundation/KIPs/kip-7#wallet-interface) can be implemented.

```solidity
// IKIP7
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);

function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
function safeTransfer(address recipient, uint256 amount, bytes data) external;
function safeTransfer(address recipient, uint256 amount) external;
function safeTransferFrom(address sender, address recipient, uint256 amount, bytes data) external;
function safeTransferFrom(address sender, address recipient, uint256 amount) external;

// IKIP7Metadata (optional)
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);

// IKIP7Mintable (optional)
function mint(address _to, uint256 _amount) external returns (bool);
function isMinter(address _account) external view returns (bool);
function addMinter(address _account) external;
function renounceMinter() external;

// IKIP7Burnable (optional)
function burn(uint256 _amount) external;
function burnFrom(address _account, uint256 _amount) external;

// IKIP7Pausable (optional)
event Paused(address _account);
event Unpaused(address _account);

function paused() external view returns (bool);
function pause() external;
function unpause() external;
function isPauser(address _account) external view returns (bool);
function addPauser(address _account) external;
function renouncePauser() external;
```

위의 인터페이스를 기반으로 개발자는 새로운 기능과 논리를 추가하여 토큰을 커스토마이징하고, Klaytn 네트워크에 배포할 수 있습니다.

For more information, refer to the official [KIP-7 documentation](https://kips.klaytn.foundation/KIPs/kip-7).

* An example implementation is available at <https://github.com/klaytn/klaytn-contracts/blob/main/contracts/KIP/token/KIP7/KIP7.sol>.

## 대체 불가 토큰 표준 (KIP-17) <a href="#non-fungible-token-standard-kip-17" id="non-fungible-token-standard-kip-17"></a>

대체 불가능한 토큰 표준(NFT, Non-fungible token)은 고유한 자산을 나타내는 특수한 토큰 유형입니다. 대체 불가능한이라는 명칭에서 알 수 있듯이, 각각의 모든 토큰은 고유하고 나눠질 수 없습니다. 대체 불가능한 토큰의 이런 고유한 특성이 자산의 디지털화를 위한 새 지평을 열어줍니다. 예를 들어 NFT는 디지털 예술, 게임 아이템, 또는 모든 종류의 고유한 자산을 나타내고, 사람들 사이에서 이들이 거래되도록 하는 데에 사용될 수 있습니다.

예를 들어, 블록체인 수집 게임인 [크립토키티](https://www.cryptokitties.co/)는 다른 유전 정보를 가진 고양이를 표현하기 위해 대체 불가능한 토큰을 구현합니다. 모든 고양이는 고유하고 상호 교환이 불가능하며, 그 결과 고양이 토큰마다 다른 가치를 가집니다.

To implement non-fungible token, [KIP-17](https://kips.klaytn.foundation/KIPs/kip-17) can be used. KIP-17 토큰 컨트랙트는 다음에 소개할 인터페이스를 사용합니다. Please note that [KIP-13](https://kips.klaytn.foundation/KIPs/kip-13) must be implemented together. For wallet applications, [wallet interface](https://kips.klaytn.foundation/KIPs/kip-17#wallet-interface) can be implemented.

```solidity
// IKIP17
event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);
event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);

function balanceOf(address _owner) external view returns (uint256);
function ownerOf(uint256 _tokenId) external view returns (address);
function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes _data) external payable;
function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;
function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
function approve(address _approved, uint256 _tokenId) external payable;
function setApprovalForAll(address _operator, bool _approved) external;
function getApproved(uint256 _tokenId) external view returns (address);
function isApprovedForAll(address _owner, address _operator) external view returns (bool);

// IKIP17Metadata (optional)
function name() external view returns (string _name);
function symbol() external view returns (string _symbol);
function tokenURI(uint256 _tokenId) external view returns (string);

// IKIP17Enumerable (optional)
function totalSupply() external view returns (uint256);
function tokenByIndex(uint256 _index) external view returns (uint256);
function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256);

// IKIP17Mintable (optional)
function mint(address _to, uint256 _tokenId) public returns (bool);
function isMinter(address _account) public view returns (bool);
function addMinter(address _account) public;
function renounceMinter() public;

// IKIP17MetadataMintable (optional)
function mintWithTokenURI(address _to, uint256 _tokenId, string memory _tokenURI) public returns (bool);
function isMinter(address _account) public view returns (bool);
function addMinter(address _account) public;
function renounceMinter() public;

// IKIP17Burnable (optional)
function burn(uint256 _tokenId) public;

// IKIP17Pausable (optional)
event Paused(address _account);
event Unpaused(address _account);
function paused() public view returns (bool);
function pause() public;
function unpause() public;
function isPauser(address _account) public view returns (bool);
function addPauser(address _account) public;
function renouncePauser() public;
```

Based on the interface above, developers may customize tokens by adding new features and logics, and deploy them on Klaytn network.

For more information, refer to the official [KIP-17 documentation](https://kips.klaytn.foundation/KIPs/kip-17).

* An example implementation is available at <https://github.com/klaytn/klaytn-contracts/blob/main/contracts/KIP/token/KIP17/KIP17.sol>.

## Klaytn 서비스체인에 대한 토큰 표준 <a href="#token-standards-for-klaytn-service-chain" id="token-standards-for-klaytn-service-chain"></a>

서비스체인은 Klaytn의 메인 블록체인 네트워크에 기반을 두는 Klaytn의 사이드체인을 의미합니다. 서비스체인을 구현할 때, 주 체인과 서비스체인간의 가치 전송을 지원하기 위해 특별한 유형의 컨트랙트가 사용됩니다. 이 컨트랙트는 현재 개발 중에 있으며, 준비가 완료되면 Klaytn 서비스체인을 위한 토큰 스펙이 KlaytnDocs에 제공될 것입니다.

## 참고: ERC-20과 ERC-721 <a href="#notes-on-erc-20-and-erc-721" id="notes-on-erc-20-and-erc-721"></a>

Klaytn은 KIP-7과 KIP-17을 토큰 표준으로 사용하기 때문에, ERC-20과 ERC-721 보다는 KIP-7과 KIP-17을 사용한 대체 가능 및 대체 불가 토큰 컨트랙트 구현을 권장합니다. KIP-7과 KIP-17은 ERC-20과 ERC-721를 기반으로 하지만, Klaytn에 최적화되어 Klaytn 에코시스템에서 사용하기에 더 적합합니다. Klaytn 네트워크가 ERC-20과 ERC-721을 아직 지원하긴 하지만, ERC-20과 ERC-721은 Klaytn 에코시스템에 있는 다양한 도구들과 호환되지 않을 수 있습니다. For more information about the differences on token standards, please visit [KIP-7](https://kips.klaytn.foundation/KIPs/kip-7#differences-with-erc-20) and [KIP-17](https://kips.klaytn.foundation/KIPs/kip-17#differences-from-erc-721).


# 이더리움 컨트랙트 이식

대부분의 경우 Klaytn에서 이더리움 컨트랙트를 수정 없이 사용할 수 있습니다. 그러나 다음 두 가지 문제에 유의하셔야 합니다.

## 솔리디티 지원 <a href="#solidity-support" id="solidity-support"></a>

* Baobab 네트워크는 현재 **London** Ethereum Virtual Machine(EVM)과 호환 가능합니다.
* Cypress network is currently compatible with **London** Ethereum Virtual Machine (EVM).

{% hint style="success" %}
v1.7.0 프로토콜 업그레이드 - **Istanbul** 하드포크 및 Klaytn의 자체 사항들을 포함하는 비호환 변경이 적용됩니다. It has been enabled from block number `#75,373,312` in case of Baobab network and `#86,816,005` for the Cypress network.

v1.7.3 프로토콜 업그레이드 - **London** 하드 포크의 Base Fee를 포함한 비호환 변경이 적용됩니다. It has been enabled from block number `#80,295,291` in case of Baobab network and `#86,816,005` for the Cypress network.

v1.8.0 Protocol Upgrade - incompatible changes including Base Fee from the **London** hard fork. It has been enabled from block number `#86,513,895` in case of Baobab network and `#86,816,005` for the Cypress network.
{% endhint %}

Backward compatibility is not guaranteed with other EVM versions on Klaytn. Thus, it is highly recommended compiling Solidity code with the correct target option according to the protocol upgrade status.

* Baobab: --evm-version london
* Cypress: --evm-version london
* 그 외(private/service chain): 프로토콜 업그레이드 상태에 따라 결정

Please refer to [how to set the EVM version of solc](https://solidity.readthedocs.io/en/latest/using-the-compiler.html#setting-the-evm-version-to-target).

An example command is shown below:

```
$ solc --evm-version london contract.sol
```

## 분리된 키 쌍 <a href="#decoupled-key-pairs" id="decoupled-key-pairs"></a>

Klaytn [decouples key pairs from addresses](/content/klaytn/design/accounts#decoupling-key-pairs-from-addresses). If user [updates account](/content/klaytn/design/transactions/basic#txtypeaccountupdate), the private key for a specific account is replaced with another one. Most cases this will not affect your business logic. However if your business logic includes ecrecover, you should consider using validateSender. For more details, refer to [here](/content/smart-contract/precompiled-contracts).


# Run a Node


# 배포

Try and get familiar with Klaytn. This chapter is the starting point of your journey to Klaytn dApps.


# Endpoint Node

## Intended Audience <a href="#intended-audience" id="intended-audience"></a>

* Anyone who wants to send transactions or query the state of Klaytn network using [Klaytn APIs](/content/dapp/json-rpc) needs to do so via an Endpoint Node.
* 엔드포인트 노드는 Klaytn 네트워크의 인터페이스입니다.

## 엔드포인트 노드 개요 <a href="#endpoint-node-overview" id="endpoint-node-overview"></a>

엔드포인트 노드는 다음과 같은 역할과 기능을 합니다.

* 블록체인 데이터를 동기화합니다.
* 새로 받은 블록을 검증합니다.
* 쿼리 요청을 처리합니다.
* 트랜잭션 요청을 프록시 노드로 전송합니다.

엔드포인트 노드 설치 바이너리는 다음의 인터페이스 및 지원 프로그램과 함께 제공됩니다.

* JSON-RPC APIs: JSON-RPC server runs inside the node, and it exposes [APIs](/content/dapp/json-rpc) for Blockchain Application development. 그뿐만 아니라 노드 관리를 위한 API도 제공합니다.
* Command-line Interface: 계정 관리와 노드 환경설정 기능을 제공합니다. 또한 노드에 첨부된 대화형 자바스크립트 콘솔 창을 제공합니다. JavaScript console implements most of the [caver-js APIs](/content/dapp/sdk/caver-js).


# 시스템 요구사항

엔드포인트 노드(EN)를 실행하려면 이더리움이나 다른 블록체인에 비해 더 좋은 성능의 하드웨어가 필요합니다. 엔터프라이즈급 하드웨어가 장착된 완전한 컨센서스 노드가 블록을 생성하면 EN이 그것을 검증해야 하기 때문입니다.

EN에는 다음 사양을 권장합니다.

## H/W Specification <a href="#h-w-specification" id="h-w-specification"></a>

### Cloud VM <a href="#cloud-vm" id="cloud-vm"></a>

#### 권장 사양 <a href="#recommended-specification-based-on-aws" id="recommended-specification-based-on-aws"></a>

| vCPU | 메모리(GiB) | 스토리지(GiB) | 디스크 대역폭(Mbps) | 네트워크 대역폭(Gbps) |
| ---- | -------- | --------- | ------------- | -------------- |
| 8    | 64       | > 3,000   | 3,500         | 최대 10          |

### 베어 머신 <a href="#bare-metal-machine" id="bare-metal-machine"></a>

EN에 대한 정확한 물리적 사양을 지정하지는 않지만, 클라우드 VM 장과 유사한 하드웨어 구성을 가진 시스템이라면 EN을 운용하기에 충분합니다.

## Storage Requirements <a href="#storage-requirements" id="storage-requirements"></a>

평균 100 TPS, 평균 트랜잭션 크기 300 바이트, 그리고 1초의 블록 생성 시간을 가정 할 때 예상되는 EN 스토리지 요구 사항은 2.5GB/1일(= 300x100x86400)입니다.

## Operating System <a href="#operating-system" id="operating-system"></a>

[Amazon Linux 2](https://aws.amazon.com/ko/about-aws/whats-new/2017/12/introducing-amazon-linux-2/) 환경을 권장합니다. Klaytn binaries are fully tested on Amazon Linux 2, but they should work on other linux-based environments as well. macOS binaries are also provided for development purpose.


# 설치 가이드


# 다운로드

[다운로드 페이지](/content/installation-guide/deployment/download)에서 EN 패키지를 다운로드할 수 있습니다.


# Installation Guide

`ken`의 최신 버전은 [Download](/content/installation-guide/deployment/endpoint-node/installation-guide/download) 페이지에서 다운로드할 수 있습니다.

## Linux Archive Distribution <a href="#linux-archive-distribution" id="linux-archive-distribution"></a>

The archive file consists of the executable binary and the configuration file structured as follows.

**Note**: Do NOT alter the file structure or file name. If you change it, the node may not function correctly.

```
- bin
  |- ken
  |- kend
- conf
  |- kend.conf
```

| File Name      | File Description   |
| -------------- | ------------------ |
| bin/ken        | EN 실행 파일           |
| bin/kend       | EN 시작 및 종료 스크립트 파일 |
| conf/kend.conf | EN 환경설정 파일         |

### Installation <a href="#installation" id="installation"></a>

The installation is the uncompression of the downloaded package where you want to install the package.

```
$ tar zxf ken-vX.X.X-linux-amd64.tar.gz
```

Or,

```
$ tar zxf ken-baobab-vX.X.X-linux-amd64.tar.gz
```

**Note**: `ken-linux-amd64/bin` 디렉토리의 경로를 `$PATH` 환경 변수에 추가하여 `ken`와 `kend`를 전역적으로 실행할 수 있도록 하세요. As an example,

```
$ export PATH=$PATH:~/downloaded/path/ken-linux-amd64/bin
```

The other sections assume that the path is added to the variable.

## RPM Distribution (RHEL/CentOS/Fedora) <a href="#rpm-rhel-centos-fedora" id="rpm-rhel-centos-fedora"></a>

### Install downloaded RPM <a href="#install-downloaded-rpm" id="install-downloaded-rpm"></a>

You can install the downloaded RPM file with the following `yum` command.

```
$ yum install kend-vX.X.X.el7.x86_64.rpm
```

Or,

```
$ yum install kend-baobab-vX.X.X.el7.x86_64.rpm
```

### Install from Klaytn Yum Repo <a href="#install-from-klaytn-yum-repo" id="install-from-klaytn-yum-repo"></a>

아래와 같이 Klaytn Yum 레포지토리에서도 `kend`를 설치할 수 있습니다.

```
$ sudo curl -o /etc/yum.repos.d/klaytn.repo https://packages.klaytn.net/config/rhel/7/prod.repo && sudo yum install kend
```

### Installed Location <a href="#installed-location" id="installed-location"></a>

The installed files are located as follows.

| File Name | Location                 |
| --------- | ------------------------ |
| ken       | /usr/bin/ken             |
| kend.conf | /etc/kend/conf/kend.conf |


# 환경설정

EN 환경설정은 데이터 디렉토리를 생성하고 환경설정 파일 `kend.conf`의 환경 변수를 설정합니다.

1. EN 데이터 디렉토리를 생성합니다.
2. `kend.conf`으로 EN 환경을 설정합니다.

## EN 데이터 디렉토리 생성 <a href="#en-data-directory-creation" id="en-data-directory-creation"></a>

Klaytn 블록체인 데이터의 크기가 계속 증가한다는 사실을 고려하면 충분히 큰 스토리지를 사용하는 것이 좋습니다. 원하는 경로에 디렉토리를 생성합니다.

```
$ sudo mkdir -p /var/kend/data
```

## Update the Configuration File <a href="#update-the-configuration-file" id="update-the-configuration-file"></a>

Configuration File Location:

* 아카이브 배포의 경우 환경설정 디렉토리의 위치가 `$INSTALL_PATH/ken-linux-amd64/conf/`으로 기본 설정되어 있습니다.
* 패키지 배포의 경우 환경설정 디렉토리의 위치가 `/etc/kend/conf/`으로 기본 설정되어 있습니다.

### Add Data Directory <a href="#add-data-directory" id="add-data-directory"></a>

환경설정 파일 `kend.conf`의 데이터 디렉토리 환경 변수 `$DATA_DIR`를 업데이트해야 합니다.

```
DATA_DIR=/var/kend/data
```

## Fast Sync (Optional) <a href="#fast-sync-optional" id="fast-sync-optional"></a>

각 EN은 네트워크의 체인 데이터 사본을 갖고 있습니다. If a node is out of sync, it can obtain this data from other nodes in the network -- a process known as syncing. 새로운 EN이 처음 시작되면 네트워크로부터 전체 체인 데이터를 다운로드받아와야 합니다.

이 과정을 더 빠르게 하기 위해 EN을 시작하기 전에 체인 데이터의 스냅샷을 다운로드하여 패스트 싱크를 실행할 수 있습니다. 패스트 싱크는 EN이 처음 시작할 때 동기화하는 데에 드는 시간을 크게 줄일 수 있습니다.

Download the latest chaindata snapshot from the [Cypress snapshot archive](http://packages.klaytn.net/cypress/chaindata/) or [Baobab snapshot archive](http://packages.klaytn.net/baobab/chaindata/). `kend`을 시작하기 전에 `kend.conf`에서 설정한 DATA\_DIR 내의 스냅샷을 추출하세요.

For example:

```bash
$ tar -C ~/kend_home -xvf klaytn-cypress-chaindata-latest.tar.gz
```

Or,

```bash
$ tar -C ~/kend_home -xvf klaytn-baobab-chaindata-latest.tar.gz
```

데이터 추출 후 EN을 정상적으로 시작할 수 있습니다.

더 자세한 내용은 [Chaindata change](/content/operation-guide/chaindata-change)를 참고하세요.

## &#x20;<a href="#en-start-stop-status" id="en-start-stop-status"></a>


# EN 실행하기

다음 명령을 사용하여 엔드포인트 노드를 실행하거나 중지할 수 있습니다.

**start**

```bash
$ kend start
Starting kend: OK
```

**stop**

```bash
$ kend stop
Shutting down kend: Killed
```

**status**

```bash
$ kend status
kend is running
```


# 설치 테스트하기

엔드포인트 노드가 성공적으로 설치되어 잘 작동하는지 점검해보겠습니다.

## Process Status <a href="#process-status" id="process-status"></a>

상태 명령 `systemctl`과 `kend`을 사용하여 EN의 프로세스 상태를 확인할 수 있습니다.

### systemctl <a href="#systemctl" id="systemctl"></a>

`systemctl`은 RPM과 함께 설치되며 EN의 상태는 다음과 같이 확인할 수 있습니다.

```bash
$ systemctl status kend.service
● kend.service - (null)
   Loaded: loaded (/etc/rc.d/init.d/kend; bad; vendor preset: disabled)
   Active: active (running) since Wed 2019-01-09 11:42:39 UTC; 1 months 4 days ago
     Docs: man:systemd-sysv-generator(8)
  Process: 29636 ExecStart=/etc/rc.d/init.d/kend start (code=exited, status=0/SUCCESS)
 Main PID: 29641 (ken)
   CGroup: /system.slice/kend.service
           └─29641 /usr/local/bin/ken --networkid 1000 --datadir /kend_home --port 32323 --srvtype fasthttp --metrics --prometheus --verbosity 3 --txpool.global...

Jan 09 11:42:39 ip-10-11-2-101.ap-northeast-2.compute.internal systemd[1]: Starting (null)...
Jan 09 11:42:39 ip-10-11-2-101.ap-northeast-2.compute.internal kend[29636]: Starting kend: [  OK  ]
Jan 09 11:42:39 ip-10-11-2-101.ap-northeast-2.compute.internal systemd[1]: Started (null).
```

위 예시처럼 `Active: active (running)` 등의 현재 상태를 확인할 수 있습니다.

### kend <a href="#kend" id="kend"></a>

`kend`은 패키지와 함께 설치되며 EN의 상태는 다음과 같이 확인할 수 있습니다.

```bash
$ kend status
kend is running
```

## Logs <a href="#logs" id="logs"></a>

로그는 `kend.out` 파일에 저장되어 있고, 이 파일은 `LOG_DIR` field of the `kend.conf` 파일의 <0>LOG\_DIR\</0> 필드에서 정의된 경로에 있습니다. 노드가 제대로 작동하면 다음과 같이 매초 블록을 가져오는 것을 볼 수 있습니다.

Example:

```bash
$ tail kend.out
INFO[02/13,07:02:24 Z] [35] Commit new mining work                    number=11572924 txs=0 elapsed=488.336µs
INFO[02/13,07:02:25 Z] [5] Imported new chain segment                blocks=1 txs=0 mgas=0.000     elapsed=1.800ms   mgasps=0.000       number=11572924 hash=f46d09…ffb2dc cache=1.59mB
INFO[02/13,07:02:25 Z] [35] Commit new mining work                    number=11572925 txs=0 elapsed=460.485µs
INFO[02/13,07:02:25 Z] [35] 🔗 block reached canonical chain           number=11572919 hash=01e889…524f02
INFO[02/13,07:02:26 Z] [14] Committed                                 address=0x1d4E05BB72677cB8fa576149c945b57d13F855e4 hash=1fabd3…af66fe number=11572925
INFO[02/13,07:02:26 Z] [5] Imported new chain segment                blocks=1 txs=0 mgas=0.000     elapsed=1.777ms   mgasps=0.000       number=11572925 hash=1fabd3…af66fe cache=1.59mB
INFO[02/13,07:02:26 Z] [35] Commit new mining work                    number=11572926 txs=0 elapsed=458.665µs
INFO[02/13,07:02:27 Z] [14] Committed                                 address=0x1d4E05BB72677cB8fa576149c945b57d13F855e4 hash=60b9aa…94f648 number=11572926
INFO[02/13,07:02:27 Z] [5] Imported new chain segment                blocks=1 txs=0 mgas=0.000     elapsed=1.783ms   mgasps=0.000       number=11572926 hash=60b9aa…94f648 cache=1.59mB
INFO[02/13,07:02:27 Z] [35] Commit new mining work      
```

## 쿼리 <a href="#queries" id="queries"></a>

### ken 콘솔 <a href="#ken-console" id="ken-console"></a>

Klaytn은 `ken console`이라는 CLI 클라이언트를 제공합니다. Another way of using the client is to connect to the process via IPC (inter-process communication). `klay.ipc` IPC 파일은 EN의 `data` 디렉토리에 있습니다.

Please execute the following command and check out the result.

```
$ ken attach /var/kend/data/klay.ipc
Welcome to the Klaytn JavaScript console!

instance: Klaytn/vX.X.X/XXXX-XXXX/goX.X.X
 datadir: /var/kend/data
 modules: admin:1.0 debug:1.0 governance:1.0 istanbul:1.0 klay:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0
 >
```

You can check the usable commands on [API Document](/content/dapp/json-rpc)

EN의 상태를 확인하는 유용한 API는 다음과 같습니다.

* `klay.blockNumber` (to get the latest block number)
* `net.peerCount` (to get the number of the connected Klaytn nodes currently)

### klay.blockNumber <a href="#klay-blocknumber" id="klay-blocknumber"></a>

최신 블록 번호를 가져와 블록이 제대로 전파되었는지 확인할 수 있습니다.

```
> klay.blockNumber
11573819
```

### net.peerCount <a href="#net-peercount" id="net-peercount"></a>

```
> net.peerCount
14
```

위 명령은 EN이 연결한 노드의 수를 반환합니다.


# ken CLI 명령어

`ken` Klaytn 엔드포인트 노드의 커맨드라인 인터페이스(CLI)입니다.

```bash
USAGE:
   ken [options] command [command options] [arguments...]
```

## 명령어 <a href="#commands" id="commands"></a>

`ken`에는 다음의 명령어들이 있습니다.

```bash
COMMANDS:
   account     Manage accounts
   attach      Start an interactive JavaScript environment (connect to node)
   console     Start an interactive JavaScript environment
   dumpconfig  Show configuration values
   dumpgenesis Dump genesis block JSON configuration to stdout (This command is supoported from Klaytn v1.7.0.)
   init        Bootstrap and initialize a new genesis block
   snapshot    A set of commands based on the snapshot
   version     Show version number
   help, h     Shows a list of commands or help for one command
```

`-h` 옵션을 사용하여 각 명령에 대한 자세한 사용법을 확인해주세요.

```bash
$ ken account -h
Manage accounts, list all existing accounts, import a private key into a new
account, create a new account or update an existing account.
 ...
Keys are stored under <DATADIR>/keystore.
It is safe to transfer the entire directory or the individual keys therein
between klay nodes by simply copying.

Make sure you backup your keys regularly.

USAGE:
   ken account command [command options] [arguments...]

COMMANDS:
     list    Print summary of existing accounts
     new     Create a new account
     update  Update an existing account
     import  Import a private key into a new account
```

```bash
$ ken init -h
init [command options] [arguments...]

The init command initializes a new genesis block and definition for the network.
This is a destructive action and changes the network in which you will be
participating.
 ...
```

## JavaScript Console <a href="#javascript-console" id="javascript-console"></a>

Klaytn Endpoint Node comes with JavaScript console. From the console command line, you can initiate part of Klaytn API calls to your EN. To attach to the JavaScript console, execute the following command.

```bash
$ ken attach ~/kend_home/klay.ipc
Welcome to the Klaytn JavaScript console

!instance: Klaytn/vX.X.X/XXXX-XXXX/goX.X.X
 datadir: ~/kend_home
 modules: admin:1.0 debug:1.0 governance:1.0 istanbul:1.0 klay:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0

 >
```

명령어 `attach`는 이미 실행 중인 노드에 연결하고, 명령어 `console`은 노드를 새로 실행시키고 연결합니다.

```bash
   attach       대화형 자바스크립트 환경을 시작합니다 (노드에 연결합니다)
   console      대화형 자바스크립트 환경을 시작합니다
```

### 모듈 API <a href="#module-apis" id="module-apis"></a>

콘솔 프롬프트에 모듈명을 입력하면 해당 모듈에서 사용 가능한 프로퍼티와 함수 목록이 표시됩니다. For the details of functions, please see [Klaytn API](/content/dapp/json-rpc).

```javascript
> personal
{
  listAccounts: [...],
  listWallets: [...],
  deriveAccount: function(),
  ecRecover: function(),
  getListAccounts: function(callback),
  getListWallets: function(callback),
  importRawKey: function(),
  lockAccount: function(),
  ...
}

> personal.listAccounts
["0x960dba2500ab529693ef8e299210768aa0d55ec8", "0x09a04dc9ac3cd92de5ff0d45ae50ff1b618305d9", "0x36662211c072dadbf5fc1e087ddebd36df986abd", "0xbf9683cf04520eeba6d936a3478de29437c5d048"]
> 
```


# JSON-RPC API

엔드포인트 노드는 JSON-RPC API로 접근할 수 있습니다. 다음과 같이 API를 활성화하거나 비활성화할 수 있습니다. For the detailed API specification, please refer to the [JSON-RPC APIs](/content/dapp/json-rpc).

**NOTE**: HTTP (`rpc`) 또는 웹소켓 (`ws`) 인터페이스를 통한 API를 제공하는 것은 인터페이스 (dApp, 브라우저 탭 등)에 접근할 수 있는 누구에게나 API에 접근할 수 있도록 하는 것입니다. 활성화한 API들에 대해 주의하세요. 기본적으로 Klaytn에서는 IPC (`ipc`) 인터페이스를 통한 모든 API가 활성화되어 있지만, `rpc`와 `ws`의 경우 모듈을 직접 활성화해야 합니다.

### API 활성화 <a href="#enabling-apis" id="enabling-apis"></a>

#### 커맨드라인을 통한 활성화 <a href="#from-commandline" id="from-commandline"></a>

Klaytn RPC 엔드포인트를 통해 API를 제공하려면 커맨드라인의 `--${interface}api` 인자를 통해 지정해주세요. 즉 `${interface}`을 HTTP 엔드포인트의 경우 `rpc`으로, 웹소켓 엔드포인트의 경우 `ws`로 설정해주세요.

`ipc`는 플래그 없이 unix 소켓 (Unix) 또는 명명된 파이프 (Windows) 엔드포인트를 통한 API를 제공합니다.

You can launch a Klaytn node with specific APIs you want to add like the example below. But keep in mind that you can't change APIs once you launch the node.

예시) `klay`와 `net` 모듈을 활성화하며 Klaytn 노드 실행하기

```shell
$ ken --rpcapi klay,net --rpc --{other options}
```

The HTTP RPC interface must be explicitly enabled using the `--rpc` flag.

#### 환경설정을 통한 활성화 <a href="#using-configuration" id="using-configuration"></a>

Please update the `RPC_ENABLE`, `RPC_API`, `WS_ENABLE` and `WS_API` properties in the [Configuration File](/content/operation-guide/configuration).

### 활성화된 API 조회 <a href="#querying-enabled-apis" id="querying-enabled-apis"></a>

To determine which APIs an interface provides, the `modules` JSON-RPC method can be invoked. 예를 들어 `rpc` 인터페이스의 경우 다음과 같습니다.

**IPC**

```javascript
$ echo '{"jsonrpc":"2.0","method":"rpc_modules","params":[],"id":1}' | nc -U klay.ipc
```

**HTTP**

```shell
$ curl -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"rpc_modules","params":[],"id":1}' https://public-en-baobab.klaytn.net
```

will give all enabled modules including the version number:

```
{
   "jsonrpc":"2.0",
   "id":1,
   "result":{
      "admin":"1.0",
      "debug":"1.0",
      "klay":"1.0",
      "miner":"1.0",
      "net":"1.0",
      "personal":"1.0",
      "rpc":"1.0",
      "txpool":"1.0",
      "web3":"1.0"
   }
}
```

### Disabling unsafe debug APIs <a href="#disabling-unsafe-debug-apis" id="disabling-unsafe-debug-apis"></a>

Some debug namespace APIs are unsafe/unappropriate to be opened to public. We recommend you to provide the debug namespace APIs to authorized users only. However, if you want to maintain a public EN and provide debug namespace APIs to the public, we strongly recommend you to set the `rpc.unsafe-debug.disable` flag which will disable APIs that are unsafe/unappropriate to be opened to the public and enable only a subset of the debug namespace APIs.

The enabled APIs are as follows:

* [VM Tracing](/content/dapp/json-rpc/api-references/debug/tracing) APIs, however with limited functionality (only [pre-defined tracers](/content/dapp/json-rpc/api-references/debug/tracing#tracing-options) are allowed)
* debug\_dumpBlock, debug\_dumpStateTrie, debug\_getBlockRlp, debug\_getModifiedAccountsByHash, debug\_getModifiedAccountsByNumber, debug\_getBadBlocks, debug\_getModifiedStorageNodesByNumber
* debug\_metrics

To set the `rpc.unsafe-debug.disable` flag, append the following line in the `kend.conf` file.

```
ADDITIONAL="$ADDITIONAL --rpc.unsafe-debug.disable"
```


# 코어 셀

## 튜토리얼 대상 <a href="#intended-audience" id="intended-audience"></a>

* 코어 셀 연산자
* Klaytn에서 블록체인 애플리케이션을 만들고 실행하는 데 관심이 있다면, 코어 셀을 유지할 필요가 없습니다. 대신 애플리케이션이 Klaytn 네트워크와 상호작용하도록 [엔드포인트 노드](/content/installation-guide/deployment/endpoint-node)를 실행해야 합니다.

## Core Cell Overview <a href="#core-cell-overview" id="core-cell-overview"></a>

코어 셀(Core Cell, CC)은 합의 프로세스에 참여하고, 트랜잭션 수행 및 블록 생성을 담당하는 요소입니다. Klaytn 코어 셀(CC)은 다음 요소로 구성됩니다.

* 컨센서스 노드(CN): 컨센서스 노드는 블록 생성 프로세스에 참여하고 있습니다.
* 프록시 노드(PN): 프록시 노드는 네트워크에 인터페이스를 제공합니다. PNs transmit the transaction requests to the Consensus Nodes, and propagate the blocks down to the Endpoint Nodes.

코어 셀은 하나의 CN과 두 개 이상의 PN으로 구성하는 것이 좋습니다. CN은 코어 셀 네트워크 내의 다른 CN에 연결하여 합의를 수행합니다. CN은 동일한 코어 셀에있는 PN의 연결만 수락하여 트랜잭션 요청을 수신하고 블록을 네트워크에 전파합니다. PN은 엔드포인트 노드 네트워크 내의 모든 EN에서 연결을 허용합니다.

![코어 셀 개요](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-d8e345200e2085511ef8c2b07f6569232e7a9dbc%2Fcn_set.png?alt=media)

| Name | Description                                                                                                                                                                                                                  | 네트워크 보안                                                                                                                                                                                           | Quantity                         |
| ---- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- |
| CN   | 코어 셀 네트워크에서 다른 CN과 새로운 블록을 생성하는 노드                                                                                                                                                                                           | 네트워크는 허가된 CN으로 구성됩니다. (IP 액세스 제어 필요).                                                                                                                                                             | 1개                               |
| PN   | <p>- Klaytn 엔드포인트 노드 네트워크에서 받은 트랜잭션을 CN에 제출하는 노드.<br>- It propagates the created blocks to Klaytn Endpoint Node Network.<br>- It can scale out horizontally depending on the number of ENs in the Endpoint Node Network.</p> | <p>- 코어 셀의 CN에 연결되어 있으며, 인터넷의 다른 Klaytn 노드에서 연결을 수락하기 위해 IP 및 포트가 공용이어야 합니다.<br>- It can connect to other PNs in other Core Cell via PN bootnode.<br>- It can connect to ENs via EN bootnode.</p> | 적어도 하나는 필요합니다. 2개 이상의 PN이 권장됩니다. |


# System Requirements

## 하드웨어 사양 <a href="#h-w-specification" id="h-w-specification"></a>

네트워크 성능은 네트워크 내 가장 성능이 떨어지는 하드웨어 사양에 따라 측정됩니다. 블록체인 네트워크 구조에서는 수직적 확장(하드웨어 용량 증가)만 가능합니다. 따라서 네트워크 내의 모든 노드는 적어도 최상 수준의 서로 비슷한 사양을 가진 하드웨어로 구성하는 것을 추천합니다.

If you're curious about the rationale of this hardware spec, the medium article [Determining optimal hardware specs for Klaytn node operators](https://klaytn.foundation/node-operator-optimal-specs/) would help you understand.

다음 장에서는 CN 및 PN 권장 사양을 보여줍니다.

### 베어메탈 서버 <a href="#bare-metal-server" id="bare-metal-server"></a>

| Category | 사양                                                                                                                                                   |
| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| 서버       | Intel® Server System [M50CYP1UR212](https://www.intel.sg/content/www/xa/en/products/sku/214842/intel-server-system-m50cyp1ur212/specifications.html) |
| CPU      | Intel® Xeon 8358 2.60 GHz (32-core/64-thread)                                                                                                        |
| 메모리      | 128GB (32GB \* 4)                                                                                                                                    |
| Storage  | 3TB (또는 더 큰 용량의) SSD (체인 데이터 크기에 따라 적절한 스토리지 크기와 환경설정이 달라질 수 있습니다. 자세한 내용은 Klaytn 팀에게 문의하시기 바랍니다.)                                                   |

이는 CN 및 PN에 권장되는 하드웨어 사양이며, 정확히 필요한 요구 사항은 아닙니다. 하드웨어 환경설정이 비슷하면 어떤 물리적 시스템이라도 CN 또는 PN을 작동시키기에 충분합니다.

### 클라우드 VM <a href="#cloud-vm" id="cloud-vm"></a>

#### AWS 권장 사양 <a href="#recommended-specification-for-aws" id="recommended-specification-for-aws"></a>

| 노드 타입 |     모델명     | vCPU 수 | 메모리 (GiB) |  스토리지 크기 (GiB)  | 스토리지 속도 (IOPS) | 가격 (서울 지역, USD/h) |
| :---: | :---------: | :----: | :-------: | :-------------: | :------------: | :---------------: |
|   CN  | m6i.8xlarge |   32   |    128    |    3,000 (최소)   |      9,000     |       1.888       |
|   PN  | m6i.4xlarge |   16   |     64    | 3,000 (Minimum) |      9,000     |       0.944       |

This storage specification is derived from AWS EBS SSD (gp3) specification.

위 정보의 출처는 <https://aws.amazon.com/ec2/instance-types/>과 <https://aws.amazon.com/ec2/pricing/on-demand/>이며, AWS에 의해 변경될 수도 있습니다.

#### Azure 권장 사양 <a href="#recommended-specification-for-azure" id="recommended-specification-for-azure"></a>

| Node Type |  Model  | vCPU | Memory (GiB) | 스토리지 타입 (GiB) | Storage speed (IOPS) | 비용 (Korea Central, USD/h) |
| :-------: | :-----: | :--: | :----------: | :-----------: | :------------------: | :-----------------------: |
|     CN    | D32s v5 |  32  |      128     |   P50 (4096)  |         7500         |           1.888           |
|     PN    | D16s v5 |  16  |      64      |   P50 (4096)  |         7500         |           0.944           |

이 스토리지 스펙은 Azure Premium Disk 스펙을 참조했습니다.

위 정보의 출처는 <https://azure.microsoft.com/en-us/pricing/details/virtual-machines/series/>과 <https://azure.microsoft.com/en-us/pricing/details/managed-disks/#pricing>이며, Microsoft에 의해 변경될 수도 있습니다.

## 스토리지 요구사항 <a href="#storage-requirements" id="storage-requirements"></a>

평균 100 TPS, 평균 트랜잭션 크기 300 바이트, 그리고 1초의 블록 생성 시간을 가정 할 때 예상되는 스토리지 요구 사항은 2.5GB/1일 (= 300x100x86400) 입니다.

## 운영 체제 <a href="#operating-system" id="operating-system"></a>

권장 환경은 RHEL (7.8 이상) 호환입니다. Klaytn 바이너리는 Amazon Linux 2에서 충분히 테스트 되었고, 리눅스 기반의 다른 환경에서도 동작합니다. 또한 개발 지원을 위해 macOS 용 바이너리도 제공하고 있습니다.


# 네트워크 설정

코어 셀은 다음으로 구성 될 수 있습니다:

* 여러 서브넷(권장)
* 단일 서브넷

## 여러 서브넷이 있는 코어 셀 <a href="#a-core-cell-with-multiple-subnets" id="a-core-cell-with-multiple-subnets"></a>

DB + AppServer 및 프록시 웹 서버와 같은 일반 웹 서비스에 사용되는 2-레이어 서브넷을 사용하는 것이 좋습니다. 이 서브넷 디자인은 보안에 더 많은 이점을 제공합니다.

모든 서버를 다른 레이어로 관리하려면 모니터링 서버도 필요하므로, 다음 장에서는 3-레이어 서브넷으로 코어 셀을 설정하는 방법에 대해 설명합니다.

3-레이어 서브넷은 다음으로 구성됩니다:

* CN 서브넷
* PN 서브넷
* 관리(Mgmt) 서브넷

### CN 서브넷 <a href="#cn-subnet" id="cn-subnet"></a>

CN 서브넷은 코어 셀의 CN 서버로 구성됩니다. 코어 셀에서 작동하는 CN은 하나이지만, 높은 가용성을 위해 여분의 CN을 준비해야 합니다. CCN (Core Cell Network) 내의 모든 CN의 IP/포트는 코어 셀 외부에서 다른 CN에 연결을 시도하기 때문에 서로에게 열려 있어야 합니다. (This connection information can be received from Baobab operators.) The internal communication with other subnets in the Core Cell requires to open default port (32323: default Klaytn P2P port number) in order to connect to PNs of the PN Subnet. 또한 모니터링 서버를 위한 CN 모니터링 포트 (61001) 및 관리 목적을 위한 SSH 포트 (22)와 같은 다른 포트들을 열어야 합니다. 멀티채널 기능을 사용하는 경우 다른 포트 (32324: 기본 멀티채널 포트)도 열어야 합니다.

![CN Subnet](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-5b87b05d5eb8a523131c85c79abf2f88354da1f8%2Fcn_subnet.png?alt=media)

| 오리진 서브넷   | 타겟 서브넷    | Ingress                      | Egress |
| --------- | --------- | ---------------------------- | ------ |
| CN Subnet | PN Subnet | P2P : 32323 (멀티채널의 경우 32324) | 전부     |
| CN Subnet | 관리 서브넷    | SSH : 22, 모니터링 : 61001       | All    |
| CN Subnet | 공개(인터넷)   | 각 CN의 IP 및 P2P 포트            | All    |

### PN 서브넷 <a href="#pn-subnet" id="pn-subnet"></a>

PN 서브넷은 외부 EN에 연결하기 위한 서비스를 제공하기 위해 PN 서버로 구성됩니다.

PN 서브넷은 다음 노드에 연결되어 있습니다:

* 코어 셀의 CN
* 다른 코어 셀의 일부 PN
* 코어 셀 관리 서버(Mgmt, 모니터링)
* EN 노드

![PN Subnet](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-1112cdc5d1e4769a5aa28714578d221da69af524%2Fpn_subnet.png?alt=media)

| Origin Subnet | Target Subnet     | Ingress                             | Egress |
| ------------- | ----------------- | ----------------------------------- | ------ |
| PN Subnet     | CN Subnet         | P2P: 32323 (32324 for multichannel) | All    |
| PN Subnet     | Mgmt Subnet       | SSH: 22, Monitoring: 61001          | All    |
| PN Subnet     | Public (Internet) | P2P: 32323                          | All    |

### 관리 서브넷 <a href="#mgmt-subnet" id="mgmt-subnet"></a>

관리 서브넷은 운영자가 ssh를 통해 코어 셀 노드에 입력 할 수 있도록 하는 게이트웨이 서브넷입니다. 코어 셀 노드를 관리하기 위한 도구가 설치된 모니터링 서버 및 관리 서버와 연결하려면 VPN 서버가 필요할 수 있습니다.

![관리 서브넷](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-2ed78d5dfec67057310f2754eb91126334df7e77%2Fadmin_subnet.png?alt=media)

| Origin Subnet | Target Subnet     | Ingress                         | Egress |
| ------------- | ----------------- | ------------------------------- | ------ |
| Mgmt Subnet   | CN Subnet         | All                             | All    |
| Mgmt Subnet   | PN Subnet         | All                             | All    |
| Mgmt Subnet   | Public (Internet) | VPN (tcp): 443, VPN (udp): 1194 | All    |

## 단일 서브넷을 가진 코어 셀 <a href="#a-core-cell-with-a-single-subnet" id="a-core-cell-with-a-single-subnet"></a>

코어 셀의 단일 서브넷은 개발/테스트 목적으로 또는 여러 서브넷을 생성하기 어려운 상황에서 구축되어집니다.

모든 노드는 단일 CC 서브넷에서 설정됩니다. CN이 P2P 포트(멀티채널 옵션의 경우 32323, 32324)를 사용하여 CNN 내의 다른 CN에 연결하려면 방화벽 설정이 필요합니다. PN의 P2P 포트는 엔드포인트 노드 네트워크(ENN)의 EN 및 코어 셀 네트워크(CNN)의 PN에 연결하기 위해 열립니다. 또한 선택적인 VPN 및 모니터링 서버를 원격으로 관리해야합니다.

![단일 서브넷을 가진 CC](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-ac274afce048fa677f8948a8eecf7dad65a4c43d%2Fcc_single_subnet.png?alt=media)


# Installation Guide


# Download

You can get packages for CN, and PN in the [download page](/content/installation-guide/deployment/download).


# 설치하기 전에

Klaytn 패키지를 설치하기 전에, 노드 URI를 등록하기 위해 연관된 노드 정보를 작성해야 합니다. Kgen 패키지가 CC 운영자를 위해 제공됩니다. 아래 순서대로 진행해주세요.

1. `kgen` 패키지 다운로드
2. Node Key & 노드 URI 생성
3. 노드 URI 등록

## Download `kgen` Package <a href="#download-kgen-package" id="download-kgen-package"></a>

우선, 운영 체제에 따라 [Download](/content/installation-guide/deployment/core-cell/installation-guide/download) 페이지에서 최신 버전의 `kgen` 패키지를 다운로드합니다.

`bin` 디렉토리에서 `kgen` 바이너리를 찾을 수 있습니다.

## 노드 키 & 노드 URI 생성 <a href="#node-key-node-uri-creation" id="node-key-node-uri-creation"></a>

노드 키와 노드 URI는 처음에 한 번만 생성됩니다. 노드 URI는 코어 셀 네트워크의 다른 코어 셀과 공유되어야 합니다. CN은 다른 CN에 연결되고 PN은 작성된 노드 URI를 사용하여 CN 및 일부 PN에 연결됩니다. 다운로드 한 `kgen`을 사용하여 노드 키를 기반으로 노드 URI가 생성됩니다. 아래 커맨드라인은 `nodekey`와 `node_info.json`를 생성합니다.

`kgen`는 다음과 같은 관련된 IP 및 포트 번호를 갖습니다.

```
$ kgen --ip "123.456.789.012" --port 32323 --file
$ ls
nodekey node_info.json
```

`nodekey`는 노드에서 내부적으로 사용되는 개인키인 64바이트 16진수 문자열입니다. 이 개인키는 Klaytn 데이터 디렉토리에 있어야 하며 잃어버리지 않도록 주의해야 합니다.

```
$ cat nodekey
f08f2118c455a6c9c9b5e035d3571e570a719ea61771e268546e796a264acc2b
$ mv nodekey ~/kcnd_home
```

생성된 `node_info.json` 파일은 다음 내용을 포함합니다.

| 키 이름        | Description | Example                                                                                                                                                                  |
| ----------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| NodeAddress | 연관된 노드들의 주소 | 0xc8a23d67f2471066fa1b07270651fea7e5c0cf78                                                                                                                               |
| NodeKey     | 노드 키 (개인키)  | aaa7248dfdf19418ae9121a0f39db39c5c27a3e404ea7c1b8e020ca8dbe7e71a                                                                                                         |
| NodeURI     | node URI    | kni://4f2f47f3bf35a2c576d3345e6e9c49b147d510c05832d2458709f63c3c90c76ead205975d944ed65e77dd4c6f63ebe1ef21d60da95952bc1e200e7487f4d9e1b\@123.456.789.012:32323?discport=0 |

`node_info.json`는 다음과 같이 JSON 형식의 노드 정보를 포함합니다.

```
$ cat node_info.json
{
    "NodeAddress": "0xc8a23d67f2471066fa1b07270651fea7e5c0cf78",
    "NodeKey": "aaa7248dfdf19418ae9121a0f39db39c5c27a3e404ea7c1b8e020ca8dbe7e71a",
    "NodeURI": "kni://4f2f47f3bf35a2c576d3345e6e9c49b147d510c05832d2458709f63c3c90c76ead205975d944ed65e77dd4c6f63ebe1ef21d60da95952bc1e200e7487f4d9e1b@123.456.789.012:32323?discport=0"
}
```

## 노드 URI 등록 <a href="#node-uri-enrollment" id="node-uri-enrollment"></a>

작성된 노드 URI는 Core Cell Network (CCN)에 참여하도록 등록해야 합니다. 등록 절차는 다음과 같습니다.

1. 관련 IP 및 포트 번호를 포함하는 `kgen` (`node_info.json`)을 사용하여 노드 URI를 생성합니다.
2. Klaytn 공식 이메일로 정보를 전송합니다. (Cypress에 대해 `bootstrap@klaytn.com` 또는 Baobab에 대해 `baobab@klaytn.com`).

등록된 정보는 공식 Klaytn 이메일 주소로 보내야 합니다. 양식은 아래와 같습니다.

CN의 경우,

```
Company: Kakao
CN URI : kni://
4f2f47f3bf35a2c576d3345e6e9c49b147d510c05832d2458709f63c3c90c76ead205975d944ed65e77dd4c6f63ebe1ef21d60da95952bc1e200e7487f4d9e1b@123.456.789.012:32323?discport=0
```

PN의 경우,

```
Company: Kakao
PN URI : kni://
4f2f47f3bf35a2c576d3345e6e9c49b147d510c05832d2458709f63c3c90c76ead205975d944ed65e77dd4c6f63ebe1ef21d60da95952bc1e200e7487f4d9e1b@123.456.789.012:32323?discport=0
```


# 컨센서스 노드 설정


# Installation Guide

`kcn`의 최신 버전은 [Download](/content/installation-guide/deployment/core-cell/installation-guide/download) 페이지에서 다운로드할 수 있습니다.

## Linux 아카이브 배포 <a href="#linux-archive-distribution" id="linux-archive-distribution"></a>

아카이브 파일은 아래와 같이 바이너리 실행 파일과 환경설정 파일로 구성되어 있습니다.

**Note**: 파일 구조 또는 파일 이름을 변경하지 마세요. 변경할 경우 노드가 올바르게 작동하지 않을 수 있습니다.

```
- bin
  |- kcn
  |- kcnd
- conf
  |- kcnd.conf
```

| 파일명            | 파일 설명              |
| -------------- | ------------------ |
| bin/kcn        | CN 실행 파일           |
| bin/kcnd       | CN 시작 및 종료 스크립트 파일 |
| conf/kcnd.conf | CN 환경설정 파일         |

### Installation <a href="#installation" id="installation"></a>

패키지를 설치하려는 곳에 다운로드 패키지의 압축을 해제합니다.

```bash
$ tar zxf kcn-vX.X.X-linux-amd64.tar.gz
```

Or,

```bash
$ tar zxf kcn-baobab-vX.X.X-linux-amd64.tar.gz
```

**Note**: `kcn-linux-amd64/bin` 디렉토리의 경로를 `$PATH` 환경 변수에 추가하여 `kcn`와 `kcnd`를 전역적으로 실행할 수 있도록 하세요. 예를 들어,

```bash
$ export PATH=$PATH:~/downloaded/path/kcn-linux-amd64/bin
```

앞으로 이 경로가 환경 변수에 추가되어 있다고 가정하고 안내하겠습니다.

## RPM 배포 (RHEL/CentOS/Fedora) <a href="#rpm-rhel-centos-fedora" id="rpm-rhel-centos-fedora"></a>

### 다운로드한 RPM을 설치 <a href="#install-downloaded-rpm" id="install-downloaded-rpm"></a>

아래와 같이 `yum` 명령을 사용하여 다운로드한 RPM 파일을 설치할 수 있습니다.

```bash
$ yum install kcnd-vX.X.X.el7.x86_64.rpm
```

Or,

```bash
$ yum install kcnd-baobab-vX.X.X.el7.x86_64.rpm
```

### Klaytn Yum 레포지토리에서 설치 <a href="#install-from-klaytn-yum-repo" id="install-from-klaytn-yum-repo"></a>

아래와 같이 Klaytn Yum 레포지토리에서도 `kcnd`를 설치할 수 있습니다.

```bash
$ sudo curl -o /etc/yum.repos.d/klaytn.repo https://packages.klaytn.net/config/rhel/7/prod.repo && sudo yum install kcnd
```

### 설치 위치 <a href="#installed-location" id="installed-location"></a>

설치된 파일은 다음의 위치에 있습니다.

| File Name | 위치                       |
| --------- | ------------------------ |
| kcn       | /usr/bin/kcn             |
| kcnd.conf | /etc/kcnd/conf/kcnd.conf |


# Configuration

CN 환경설정은 데이터 디렉토리를 생성하고 환경설정 파일 `kcnd.conf`의 여러 변수를 설정합니다.

1. CN 데이터 디렉토리 생성
2. 노드 키 설치
3. `kcnd.conf`으로 CN 환경을 설정합니다.

## CN 데이터 디렉토리 생성 <a href="#cn-data-directory-creation" id="cn-data-directory-creation"></a>

Klaytn 블록체인 데이터의 크기는 계속 증가하므로, 충분히 큰 스토리지를 사용하는 것을 추천합니다. 원하는 경로에 디렉토리를 생성할 수 있습니다.

```bash
$ mkdir -p /var/kcnd/data
```

## 노드 키 설치 <a href="#install-node-key" id="install-node-key"></a>

CN을 작동시키기 위해 `nodekey`가 필요합니다. 만일 nodekey가 없다면 KCN 바이너리가 새로 생성해 줄 것입니다. 만일 이미 가지고 있다면 `nodekey`를 CN 데이터 디렉토리에 넣으세요. `nodekey`를 생성하는 방법은 '[Before You Install](/content/installation-guide/deployment/core-cell/installation-guide/before-you-install)' 장에 설명되어 있습니다. 다음 커맨드라인은 `nodekey`를 CN 데이터 디렉토리에 복사합니다.

```bash
$ cp nodekey /var/kcnd/data
```

## 환경설정 파일 업데이트 <a href="#update-the-configuration-file" id="update-the-configuration-file"></a>

환경설정 파일 위치는 다음과 같습니다.

* 아카이브 배포의 경우 환경설정 디렉토리의 위치가 `$INSTALL_PATH/kcn-linux-amd64/conf/`으로 기본 설정되어 있습니다.
* 패키지 배포의 경우 환경설정 디렉토리의 위치가 `/etc/kcnd/conf/`으로 기본 설정되어 있습니다.

### 데이터 디렉토리 추가 <a href="#add-data-directory" id="add-data-directory"></a>

환경설정 파일 `kcnd.conf`의 데이터 디렉토리 환경 변수 `$DATA_DIR`를 업데이트해야 합니다.

```
...
DATA_DIR=/var/kcnd/data
...
```

### Rewardbase 설정 <a href="#setup-rewardbase" id="setup-rewardbase"></a>

Klaytn 네트워크 컨센서스에 참여한 것에 대한 보상으로, CN 운영자는 KLAY를 받습니다. 이러한 이유로 환경설정 파일 `kcnd.conf`에 주소를 설정해야 합니다.

새 계정을 만드는 방법은 다양하지만, `kcn`도 본 기능을 제공합니다. 다음 명령으로 도움말을 확인할 수 있습니다.

```bash
$ kcn account new --help
```

이 절차를 수행하는 예시 중 하나는 다음과 같습니다. 우선, KLAY 보상을 받을 새 계정을 만들어야 합니다.

```bash
$ kcn account new --datadir ~/kcnd_home
INFO[03/15,09:04:43 +09] [17] Setting connection type                   nodetype=cn conntype=-0
INFO[03/15,09:04:43 +09] [17] Maximum peer count                        KLAY=25 LES=0 total=25
INFO[03/15,09:04:43 +09] [17] SBN is disabled.
Your new account is locked with a password. Please give a password. Do not forget this password.
Passphrase:
Repeat passphrase:
Address: {d13f7da0032b1204f77029dc1ecbf4dae2f04241}
```

결과적으로 사용자가 정의한 경로에 연관된 키스토어가 생성됩니다. 다음으로, 생성된 주소를 다음과 같이 `kcnd.conf` 파일에 입력해야 합니다.

```
...
REWARDBASE="d13f7da0032b1204f77029dc1ecbf4dae2f04241"
...
```

생성한 키스토어와 비밀번호는 매우 중요하므로 관리에 주의해야 합니다. See more details about `kcnd.conf` on the [Configuration File](/content/operation-guide/configuration) section.

## 패스트 싱크 (선택 사항) <a href="#fast-sync-optional" id="fast-sync-optional"></a>

각 CN은 네트워크의 체인 데이터 사본을 갖고 있습니다. 어떤 노드가 동기화되어 있지 않으면 네트워크의 다른 노드로부터 데이터를 받아옵니다 -- 동기화(syncing)라고 알려진 과정입니다. 새로운 CN이 처음 시작되면 네트워크로부터 전체 체인 데이터를 다운로드받아와야 합니다.

이 과정을 더 빠르게 하기 위해 CN을 시작하기 전에 체인 데이터의 스냅샷을 다운로드하여 패스트 싱크를 실행할 수 있습니다. 패스트 싱크는 CN이 처음 시작할 때 동기화하는 데에 드는 시간을 크게 줄일 수 있습니다.

[Cypress 스냅샷 아카이브](http://packages.klaytn.net/cypress/chaindata/) 또는 [Baobab 스냅샷 아카이브](http://packages.klaytn.net/baobab/chaindata/)에서 체인 데이터의 최신 스냅샷을 다운로드할 수 있습니다. `kcnd`을 시작하기 전에 `kcnd.conf`에서 설정한 DATA\_DIR 내의 스냅샷을 추출하세요.

예를 들어,

```bash
$ tar -C ~/kcnd_home -xvf klaytn-cypress-chaindata-latest.tar.gz
```

또는

```bash
$ tar -C ~/kcnd_home -xvf klaytn-baobab-chaindata-latest.tar.gz
```

데이터 추출 후 CN을 정상적으로 시작할 수 있습니다.

You can refer to detailed information in the [Chaindata change](/content/operation-guide/chaindata-change)


# CN 실행하기

## CN 시작/중지 <a href="#cn-start-stop" id="cn-start-stop"></a>

다음 `systemctl` 명령을 사용하여 Klaytn 서비스를 시작/중지할 수 있습니다.

**참고**: 루트 권한이 필요합니다.

**실행**

```bash
$ systemctl start kcnd.service

```

**중지**

```bash
$ systemctl stop kcnd.service

```

**status**

```bash
$ systemctl status kcnd.service

```

## Troubleshooting <a href="#troubleshooting" id="troubleshooting"></a>

다음 오류가 발생하면,

```bash
Failed to start kcnd.service: Unit not found.
```

다음 명령으로 시스템 관리자 환경설정을 다시 로드하세요.

```bash
$ systemctl daemon-reload
```


# 프록시 노드 설정


# Installation Guide

`kpn`의 최신 버전은 [Download](/content/installation-guide/deployment/core-cell/installation-guide/download) 페이지에서 다운로드할 수 있습니다.

## Linux Archive Distribution <a href="#linux-archive-distribution" id="linux-archive-distribution"></a>

The archive file consists of the executable binary and the configuration file structured as follows.

**Note**: Do NOT alter the file structure or file name. If you change it, the node may not function correctly.

```
- bin
  |- kpn
  |- kpnd
- conf
  |- kpnd.conf
```

| File Name      | File Description   |
| -------------- | ------------------ |
| bin/kpn        | PN 실행 파일           |
| bin/kpnd       | PN 시작 및 종료 스크립트 파일 |
| conf/kpnd.conf | PN 환경설정 파일         |

### Installation <a href="#installation" id="installation"></a>

The installation is the uncompression of the downloaded package where you want to install the package.

```bash
$ tar zxf kpn-vX.X.X-linux-amd64.tar.gz
```

Or,

```bash
$ tar zxf kpn-baobab-vX.X.X-linux-amd64.tar.gz
```

**Note**: `kpn-linux-amd64/bin` 디렉토리의 경로를 `$PATH` 환경 변수에 추가하여 `kpn`와 `kpnd`를 전역적으로 실행할 수 있도록 하세요. As an example,

```bash
$ export PATH=$PATH:~/downloaded/path/kpn-linux-amd64/bin
```

The other sections assume that the path is added to the variable.

## RPM Distribution (RHEL/CentOS/Fedora) <a href="#rpm-rhel-centos-fedora" id="rpm-rhel-centos-fedora"></a>

### Install downloaded RPM <a href="#install-downloaded-rpm" id="install-downloaded-rpm"></a>

You can install the downloaded RPM file with the following `yum` command.

```bash
$ yum install kpnd-vX.X.X.el7.x86_64.rpm
```

Or,

```bash
$ yum install kpnd-baobab-vX.X.X.el7.x86_64.rpm
```

### Install from Klaytn Yum Repo <a href="#install-from-klaytn-yum-repo" id="install-from-klaytn-yum-repo"></a>

아래와 같이 Klaytn Yum 레포지토리에서도 `kpnd`를 설치할 수 있습니다.

```bash
$ sudo curl -o /etc/yum.repos.d/klaytn.repo https://packages.klaytn.net/config/rhel/7/prod.repo && sudo yum install kpnd
```

### Installed Location <a href="#installed-location" id="installed-location"></a>

The installed files are located as follows.

| File Name | Location                 |
| --------- | ------------------------ |
| kpn       | /usr/bin/kpn             |
| kpnd.conf | /etc/kpnd/conf/kpnd.conf |


# Configuration

PN 환경설정은 데이터 디렉토리를 생성하고 환경설정 파일 `kpnd.conf`의 여러 변수를 설정합니다.

1. PN 데이터 디렉토리 생성하기
2. Install node key
3. `static-node.json` 설치하기
4. `kpnd.conf`으로 PN 환경설정하기

## PN 데이터 디렉토리 생성 <a href="#pn-data-directory-creation" id="pn-data-directory-creation"></a>

Considering the fact that the size of Klaytn blockchain data is always increased, it is recommended to use a big enough storage. You may need to create the directory on your desired path.

```bash
$ mkdir -p /var/kpnd/data
```

## Install Node Key <a href="#install-node-key" id="install-node-key"></a>

PN을 작동시키기 위해 `nodekey`가 필요합니다. 만일 nodekey가 없다면 KCN 바이너리가 새로 생성해 줄 것입니다. 이미 가지고 있다면 `nodekey`를 PN 데이터 디렉토리에 넣어주세요. `nodekey`를 생성하는 방법은 "[Before You Install](/content/installation-guide/deployment/core-cell/installation-guide/before-you-install)" 장에 설명되어 있습니다. 다음 커맨드라인은 `nodekey`를 PN 데이터 디렉토리에 복사합니다.

```bash
$ cp nodekey /var/kpnd/data
```

## `static-nodes.json` 설치하기 <a href="#install-static-nodes-json" id="install-static-nodes-json"></a>

`static-nodes.json`은 PN 운영자로부터 생성되어야 합니다. PN이 연결된 주소들이 포함되어 있습니다. CN 및 다른 코어 셀의 PN을 포함해 주소를 추가하는 것이 좋습니다. 자세한 내용은 Klaytn 공식 이메일로 문의하세요.(Cypress 문의는 `bootstrap@klaytn.com` 또는 Baobab 문의는 `baobab@klaytn.com`).

**static-nodes.json**

```
[
  "kni://4f2f47f3bf35a2c576d3345e6e9c49b147d510c05832d2458709f63c3c90c76ead205975d944ed65e77dd4c6f63ebe1ef21d60da95952bc1e200e7487f4d9e1b@10.11.2.101:32323?discport=0&ntype=cn",
  "kni://8dee912aeda2ccfaa4fe421f015d4d75c2e3fd4aab75fa399b42767caad33531e57f3356b4a4af374593e33ec4320e1325aa2390a7be2489fa6b5724894680eb@10.11.2.102:32323?discport=0&ntype=pn"
]
```

PN의 노드 URI는 "[Before You Install](/content/installation-guide/deployment/core-cell/installation-guide/before-you-install)" 장에 있습니다. (참고: 이 IP 주소는 CN 공개 IP와 다릅니다.) 다음 커맨드라인은 `static-nodes.json` 파일을 PN 데이터 디렉토리에 복사합니다.

```bash
$ cp static-nodes.json /var/kpnd/data
```

## Update the Configuration File <a href="#update-the-configuration-file" id="update-the-configuration-file"></a>

Configuration File Location:

* 아카이브 배포의 경우 환경설정 디렉토리의 위치가 `$INSTALL_PATH/kpn-linux-amd64/conf/`으로 기본 설정되어 있습니다.
* 패키지 배포의 경우 환경설정 디렉토리의 위치가 `/etc/kpnd/conf/`으로 기본 설정되어 있습니다.

### Add Data Directory <a href="#add-data-directory" id="add-data-directory"></a>

환경설정 파일 `kpnd.conf`의 데이터 디렉토리 환경 변수 `$DATA_DIR`를 업데이트해야 합니다.

```
...
DATA_DIR=/var/kpnd/data
...
```

## Fast Sync (Optional) <a href="#fast-sync-optional" id="fast-sync-optional"></a>

각 PN은 네트워크의 체인 데이터 사본을 갖고 있습니다. If a node is out of sync, it can obtain this data from other nodes in the network -- a process known as syncing. 새로운 PN이 처음 시작되면 네트워크로부터 전체 체인 데이터를 다운로드 받아와야 합니다.

이 과정을 더 빠르게 하려면 PN을 시작하기 전에 체인 데이터의 스냅샷을 다운로드하여 패스트 싱크를 실행할 수 있습니다. 패스트 싱크는 PN이 처음 시작할 때 동기화하는 데에 드는 시간을 크게 줄일 수 있습니다.

Download the latest chaindata snapshot from the [Cypress snapshot archive](http://packages.klaytn.net/cypress/chaindata/) or [Baobab snapshot archive](http://packages.klaytn.net/baobab/chaindata/). `kpnd`을 시작하기 전에 `kpnd.conf`에서 설정한 DATA\_DIR 내의 스냅샷을 추출하세요.

For example:

```
$ tar -C /var/kpnd/data -xvf klaytn-cypress-chaindata-latest.tar.gz
```

Or,

```
$ tar -C /var/kpnd/data -xvf klaytn-baobab-chaindata-latest.tar.gz
```

데이터 추출 후 PN을 정상적으로 시작할 수 있습니다.

더 자세한 내용은 [Chaindata change](https://github.com/klaytn/klaytn-docs-ko/blob/main/docs/operation-guide/chaindata-change/README.md)를 참고하세요.


# PN 실행하기

## PN 시작/중지 <a href="#pn-start-stop" id="pn-start-stop"></a>

You can start/stop the Klaytn service with the following `systemctl` command.

**Note**: This requires root privileges.

**start**

```bash
$ systemctl start kpnd.service

```

**stop**

```bash
$ systemctl stop kpnd.service

```

**status**

```bash
$ systemctl status kpnd.service

```

## Troubleshooting <a href="#troubleshooting" id="troubleshooting"></a>

If you meet the following error,

```bash
Failed to start kpnd.service: Unit not found.
```

reload the systemd manager configuration with the following command.

```bash
$ systemctl daemon-reload
```


# 코어 셀 테스트하기

코어 셀이 성공적으로 설치되어 잘 작동하는지 점검해보겠습니다.

## 프로세스 상태 <a href="#process-status" id="process-status"></a>

상태 명령 `systemctl`과 `kcnd/kpnd`를 사용하여 CN/PN의 프로세스 상태를 확인할 수 있습니다.

### systemctl <a href="#systemctl" id="systemctl"></a>

`systemctl`은 RPM과 함께 설치되며 CN/PN의 상태는 다음과 같이 확인할 수 있습니다.

```bash
$ systemctl status kcnd.service
● kcnd.service - (null)
   Loaded: loaded (/etc/rc.d/init.d/kcnd; bad; vendor preset: disabled)
   Active: active (running) since Wed 2019-01-09 11:42:39 UTC; 1 months 4 days ago
     Docs: man:systemd-sysv-generator(8)
  Process: 29636 ExecStart=/etc/rc.d/init.d/kcnd start (code=exited, status=0/SUCCESS)
 Main PID: 29641 (kcn)
   CGroup: /system.slice/kcnd.service
           └─29641 /usr/local/bin/kcn --networkid 1000 --datadir /kcnd_home --port 32323 --srvtype fasthttp --metrics --prometheus --verbosity 3 --txpool.global...

Jan 09 11:42:39 ip-10-11-2-101.ap-northeast-2.compute.internal systemd[1]: Starting (null)...
Jan 09 11:42:39 ip-10-11-2-101.ap-northeast-2.compute.internal kcnd[29636]: Starting kcnd: [  OK  ]
Jan 09 11:42:39 ip-10-11-2-101.ap-northeast-2.compute.internal systemd[1]: Started (null).
```

위 예시처럼 `Active: active (running)` 등의 현재 상태를 확인할 수 있습니다.

### kcnd (kpnd) <a href="#kcnd-kpnd" id="kcnd-kpnd"></a>

`kcnd` (또는 `kpnd`)는 패키지와 함께 설치되며 CN/PN의 상태는 다음과 같이 확인할 수 있습니다.

```bash
$ kcnd status
kcnd is running
```

## 로그 <a href="#logs" id="logs"></a>

로그는 `kscnd.out` (또는 `kpnd.out`) 파일에 저장되어 있고, 이 파일은 `kscnd.conf` (또는 `kpnd.conf`) 파일의 `LOG_DIR` 필드에서 정의된 경로에 있습니다. 노드가 제대로 작동하면 다음과 같이 매초 블록이 생성되는 것을 볼 수 있습니다.

예시:

```bash
$ tail kcnd.out
INFO[02/13,07:02:24 Z] [35] Commit new mining work                    number=11572924 txs=0 elapsed=488.336µs
INFO[02/13,07:02:25 Z] [5] Imported new chain segment                blocks=1 txs=0 mgas=0.000     elapsed=1.800ms   mgasps=0.000       number=11572924 hash=f46d09…ffb2dc cache=1.59mB
INFO[02/13,07:02:25 Z] [35] Commit new mining work                    number=11572925 txs=0 elapsed=460.485µs
INFO[02/13,07:02:25 Z] [35] 🔗 block reached canonical chain           number=11572919 hash=01e889…524f02
INFO[02/13,07:02:26 Z] [14] Committed                                 address=0x1d4E05BB72677cB8fa576149c945b57d13F855e4 hash=1fabd3…af66fe number=11572925
INFO[02/13,07:02:26 Z] [5] Imported new chain segment                blocks=1 txs=0 mgas=0.000     elapsed=1.777ms   mgasps=0.000       number=11572925 hash=1fabd3…af66fe cache=1.59mB
INFO[02/13,07:02:26 Z] [35] Commit new mining work                    number=11572926 txs=0 elapsed=458.665µs
INFO[02/13,07:02:27 Z] [14] Committed                                 address=0x1d4E05BB72677cB8fa576149c945b57d13F855e4 hash=60b9aa…94f648 number=11572926
INFO[02/13,07:02:27 Z] [5] Imported new chain segment                blocks=1 txs=0 mgas=0.000     elapsed=1.783ms   mgasps=0.000       number=11572926 hash=60b9aa…94f648 cache=1.59mB
INFO[02/13,07:02:27 Z] [35] Commit new mining work                    number=11572927 txs=0 elapsed=483.436µs
```

## kcn 콘솔 (kpn 콘솔) <a href="#kcn-console-kpn-console" id="kcn-console-kpn-console"></a>

Klaytn은 CLI 클라이언트를 제공합니다: `kcn console` (또는 `kpn console` ). 그러나 CN/PN은 보안상의 이유로 클라이언트의 RPC 인터페이스를 비활성화할 수 있습니다. 클라이언트를 사용하는 또 다른 방법은 IPC (inter-process communication)를 통해 프로세스에 연결하는 것입니다.

`klay.ipc` IPC 파일은 CN/PN의 `data` 디렉토리에 있습니다.

다음 명령을 실행하고 결과를 확인하세요.

CN의 경우,

```bash
$ ken attach /var/kend/data/klay.ipc
Welcome to the Klaytn JavaScript console!

instance: Klaytn/vX.X.X/XXXX-XXXX/goX.X.X
 datadir: /var/kend/data
 modules: admin:1.0 debug:1.0 governance:1.0 istanbul:1.0 klay:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0
 >
```

PN의 경우,

```bash
 $ kpn attach /var/kpnd/data/klay.ipc
 Welcome to the Klaytn JavaScript console!

 instance: Klaytn/vX.X.X/XXXX-XXXX/goX.X.X
 coinbase: 0x67f68fdd9740fd7a1ac366294f05a3fd8df0ed40
 at block: 11573551 (Wed, 13 Feb 2019 07:12:52 UTC)
  datadir: /var/kpnd/data
  modules: admin:1.0 debug:1.0 istanbul:1.0 klay:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0
  >
```

You can check the usable commands on [API Document](https://github.com/klaytn/klaytn-docs-ko/blob/main/docs/installation-guide/dapp/json-rpc/README.md)

CN/PN의 상태를 확인하는 유용한 API는 다음과 같습니다.

* `klay.blockNumber` (최신 블록 번호를 가져옵니다)
* `net.peerCount` (현재 연결된 Klaytn 노드의 수를 가져옵니다)

### klay.blockNumber <a href="#klay-blocknumber" id="klay-blocknumber"></a>

노드 유형에 따라 (CN에 대해) 블록이 생성되었는지 또는 (CN 및 PN에 대해) 올바르게 전파되는지 확인하기 위해 최신 블록 번호를 얻을 수 있습니다.

```javascript
> klay.blockNumber
11573819
```

### net.peerCount <a href="#net-peercount" id="net-peercount"></a>

```javascript
> net.peerCount
14
```

위의 커맨드라인은 노드 유형에 따라 다른 값을 반환합니다.

* CN: 연결된 CN 수 + 연결된 PN 수
* PN: 연결된 CN 수 + 연결된 PN 수 + 연결된 EN 수


# 모니터링 설정

## Overview <a href="#overview" id="overview"></a>

Klaytn 팀은 Klaytn CCN을 모니터링할 수 있는 사이트(<http://cypress.klaytn.net:3000>)를 제공합니다. `telegraf` 모니터링 에이전트는 CC의 각 CN/PN에 설치되어 지표를 수집하고 이를 모니터링 서버로 보냅니다. 일단 설치되면 모니터링 사이트를 방문하여 Klaytn CC의 지표들을 볼 수 있습니다.

설치 과정은 다음과 같습니다.

1. CN/PN에서 `telegraf` 설치하기
2. `telegraf` 환경설정하기
3. `telegraf` 시작하기

## Telegraf 설치 <a href="#telegraf-installation" id="telegraf-installation"></a>

Telegraf 설치 안내서 (Amazon Linux 2 사용자, 아래 참조): <https://docs.influxdata.com/telegraf/latest/introduction/installation/>

**Amazon Linux 2에 대한 참고 사항**

Amazon Linux 2에 Telegraph를 설치하려면, 다음과 같이 InfluxData의 RHEL 7 yum repo를 사용해야 합니다:

```
cat <<EOF | sudo tee /etc/yum.repos.d/influxdb.repo
[influxdb]
name = InfluxDB Repository - RHEL 7
baseurl = https://repos.influxdata.com/rhel/7/\$basearch/stable
enabled = 1
gpgcheck = 1
gpgkey = https://repos.influxdata.com/influxdb.key
EOF
```

## Telegraf 설정 <a href="#telegraf-setup" id="telegraf-setup"></a>

### kcnd/kpnd에서 모니터링 활성화 <a href="#enable-monitoring-in-kcnd-kpnd" id="enable-monitoring-in-kcnd-kpnd"></a>

/etc/kcnd/conf/kcnd.conf

```
...
METRICS=1
PROMETHEUS=1
...
```

**Check**

포트 61001이 열려 있는지 확인하여 위의 두 가지 옵션이 활성화되어 있는지 확인할 수 있습니다.

```
$ netstat -ntap | grep 61001
tcp        0      0 :::61001        :::*       LISTEN      8989/kcn
```

**Telegraf 서비스 환경설정**

다음 파일을 `telegraf` 환경설정 디렉토리 (`/etc/telegraf/telegraf.d/`)에 복사하고, `nodetype`, `instance`, `hostname`를 각 노드에 적합하게 수정하세요.

```
[global_tags]
  # Change "cn" to "pn" for PN installation
  nodetype = "cn"

  # The CN/PN name (e.g. `example-cn`, `example-pn`)
  instance = "<hostname>"

[agent]
  # The CN/PN name (e.g. `example-cn`, `example-pn`)
  hostname = "<hostname>"

[[outputs.influxdb]]
  urls = [ "http://localhost:" ]
  database = "klaytn_cypress"

[[inputs.prometheus]]
  urls = [ "http://localhost:61001/metrics" ]
```

`/etc/telegraf/telegraf.conf`에서 다음을 변경하세요:

* `[[outputs.influxdb]]` 장을 주석 처리 하세요.

**Telegraf 시작하기**

```
$ systemctl restart telegraf
```

## Grafana <a href="#grafana" id="grafana"></a>

각 CN/PN이 위의 환경설정 및 에이전트를 가진 경우, 다음 URL에서 지표들을 확인할 수 있습니다.

<http://cypress.klaytn.net:3000>

CC 운영자는 슬랙 채널에 회사 이름과 이메일 주소를 제공하시고 계정을 요청할 수 있습니다. CC 운영자만이 Grafana 계정을 요청할 수 있습니다.


# H/A 설정

코어 셀을 효과적으로 운영하려면, 높은 가용성을 위한 CN 구성이 중요합니다. 권장되는 높은 가용성을 가지는 구성은 코어 셀이 물리적 인프라에 배포되었는지 클라우드 인프라에 배포되는지에 따라 결정됩니다.

## Active-Standby (베어메탈에 권장) <a href="#active-standby-recommended-for-bare-metal" id="active-standby-recommended-for-bare-metal"></a>

이 환경설정에서는 두 개의 CN 노드가 액티브-스탠바이 설정으로 설치됩니다. 정상 작동 중에 active 노드는 블록 생성에 참여하는 반면, standby는 네트워크의 체인데이터만 동기화합니다. 이 환경설정은 active 노드에서 장애가 발생하는 경우에도 standby CN 노드가 새로운 체인데이터 사본을 가지고 있도록 합니다.

### 설정 <a href="#setup" id="setup"></a>

1. active CN의 `nodekey`의 백업 생성하기.
2. standby CN 설치하기. 구성은 다음을 제외하고 active CN과 동일합니다:
   * standby는 다른 `nodekey`를 사용해야 합니다.
   * PN의 주소를 `$DATA_DIR/static-nodes.json`에 추가하세요.

### 장애 조치 <a href="#failover" id="failover"></a>

1. standby CN 중지: `sudo systemctl stop kcnd`
2. standby의 `nodekey`를 장애가 발생한 active CN의 `nodekey`로 대체하세요.
3. active CN의 IP 주소를 standby CN에 재지정하세요.
4. standby CN을 시작하고 네트워크와 동기화되어 있는지 확인하세요: `sudo systemctl start kcnd`

## 머신 이미지 & 스냅샷 (클라우드에 권장) <a href="#machine-image-snapshot-recommended-for-cloud" id="machine-image-snapshot-recommended-for-cloud"></a>

클라우드 인프라를 통해 운영자는 장애가 발생한 노드를 훨씬 빠르게 교체할 수 있으므로, 두 번째 standby CN을 운영할 필요가 없습니다. 대신 새로운 CN이 신속하게 공급되고 업데이트된 체인데이터 사본을 제공받는 것이 보장되는 것으로 충분합니다.

정확한 용어 및 절차는 클라우드 환경에 따라 다를 수 있습니다. 아래 절차는 AWS(특히 EC2 및 EBS)를 기반으로 하지만, 다른 클라우드 플랫폼에 맞게 조정할 수 있습니다.

### Setup <a href="#setup" id="setup"></a>

1. Create a backup of the active CN's `nodekey`.
2. CN 구성 또는 소프트웨어가 업데이트될 때마다 머신 이미지를 생성하세요(예: AMI). 이 이미지에 `DATA_DIR`을 담은 볼륨을 포함하지 마세요 - 이는 별도로 얻을 수 있습니다.

### Failover <a href="#failover" id="failover"></a>

CC의 PN 노드 중 하나를 사용하여 체인데이터 스냅샷을 얻으세요:

1. PN 노드에 연결하고 kpnd를 중지하세요: `sudo systemctl stop kpnd` . 데이터 일관성을 보장하기 위해 kpnd를 먼저 중지하는 것이 중요합니다.
2. AWS 콘솔을 사용하여 PN의 `DATA_DIR`이 포함된 볼륨의 스냅샷을 생성하세요.
3. kpnd를 중지하세요: `sudo systemctl stop kpnd`

기본 CN 이미지 및 체인데이터 이미지를 사용하여 새 CN을 생성하세요.

1. CN 이미지를 사용하여(\위의 "설정"에서 생성한) 인스턴스를 만듭니다.
2. PN의 `$DATA_DIR` 스냅샷에서 생성한 볼륨을 연결하세요.
3. `$DATA_DIR/klay/chaindata`를 제외한 볼륨의 모든 파일을 제거하세요. `kcnd.conf`에 설정된 `DATA_DIR`이 체인데이터를 포함하는 디렉토리와 일치하는지 확인하세요. 이름이 다른 경우 디렉토리 이름을 바꿔야 할 수도 있습니다.
4. 장애가 발생한 CN의 `nodekey`를 `$DATA_DIR/klay/nodekey`에 복사하세요.
5. 장애가 발생한 CN의 IP 주소를 대체재로 재지정하세요.
6. kcnd를 시작하세요: `sudo systemctl start kcnd`
7. CN이 네트워크와 동기화되어 있는지 확인하세요.

## 추가 고려 사항 <a href="#additional-considerations" id="additional-considerations"></a>

장애가 발생한 CN의 공용 IP를 대체 CN에 재할당하면 대체 CN이 다른 CN에 즉시 연결될 수 있습니다. IP가 변경되면 다른 모든 CCO가 방화벽 구성을 업데이트할 때까지 새 CN을 네트워크에 연결할 수 없습니다.


# Service Chain

## Intended Audience <a href="#intended-audience" id="intended-audience"></a>

* 높은 TPS, 낮은 트랜잭션 수수료 그리고 데이터 보호를 원하는 dApp 개발자.
* 테스트를 위해 로컬 개인 네트워크 또는 원장 데이터베이스를 구축하려는 사람.

## 서비스체인 개요 <a href="#service-chain-overview" id="service-chain-overview"></a>

Klaytn 서비스체인은 다음 기능을 제공합니다.

* Immediate finality.
* 체인 간 토큰 전송.
* 메인체인에 데이터 앵커링.
* 엔터프라이즈 보안 요구 사항을 충족하기 위한 멀티시그 브리지 컨트랙트.

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-94ffe69bfb238df5d7c2c228421f22d6f798ff49%2Fsc_connection.png?alt=media)

서비스체인에 대한 자세한 내용은 [Klaytn Scaling Solution](/content/klaytn/scaling-solutions)를 참고해주세요.


# Getting Started

이 튜토리얼의 각각 단계들을 따라 하면 클레이튼 테스트넷에 연결된 독립적인 블록체인 네트워크로 구성된 서비스체인을 빠르게 설치하고 실행해 보실 수 있습니다.

이 튜토리얼은 서비스체인 네트워크를 구성하고, 서비스체인 네트워크와 클레이튼 Baobab 네트워크를 연결하는 방법을 설명합니다. 또한 두 체인 사이에 주기적으로 데이터 앵커링이 가능하도록 설정하는 방법과 토큰을 전송하는 방법에 대해서도 설명합니다. 튜토리얼의 후반부에서는 실제로 블록체인 서비스를 운영하기 위해, 고가용성을 보장하는 방법, 여러 서비스체인을 계층적으로 구성하는 방법, 같은 계층의 서비스체인 간에 토큰을 전송하는 방법을 설명할 것입니다.

* [4개 노드 서비스 체인 설정하기](/content/installation-guide/deployment/service-chain/getting-started/4nodes-setup-guide)
* [Baobab 연결](/content/installation-guide/deployment/service-chain/getting-started/en-scn-connection)
* [체인 간 밸류 트랜스퍼](/content/installation-guide/deployment/service-chain/getting-started/value-transfer)
* [서비스 체인의 고가용성](/content/installation-guide/deployment/service-chain/getting-started/ha-for-sc)
* [네스티드 서비스 체인](/content/installation-guide/deployment/service-chain/getting-started/nested-sc)
* [형제 서비스 체인 간 토큰 전송](/content/installation-guide/deployment/service-chain/getting-started/value-transfer-between-sibling)


# 4개 노드 서비스 체인 설정하기

이 장에서는 여러 노드로 서비스체인을 구성하는 법을 설명합니다. `chainID`를 1002로 구별하여 4개의 컨센서스 노드로 구성된 서비스체인을 설치할 것입니다.

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-3b0bc6362571591a299fc7f061dc21bff640ae8b%2Fsc-4scn-arch.png?alt=media)

### Prerequisites <a href="#prerequisites" id="prerequisites"></a>

* Download packages for `kscn`, `homi` binary from [Download](/content/installation-guide/deployment/download).
* 4대의 Linux 또는 MacOS 서버
* 최소 하드웨어 요구 사항
  * CPU: 4코어(Intel Xeon 또는 동급), RAM: 16GB, HDD: 50GB
  * 자세한 설명은 [시스템 요구사항](/content/installation-guide/deployment/service-chain/references/system-requirements)을 참조하세요.

### 0 단계: 모든 노드에 SCN 설치하기 <a href="#install-scn" id="install-scn"></a>

다운로드한 kscn 패키지를 압축 해제하고, 압축해제된 파일들을 각 노드로 복사합니다.

```console
$ tar xvf kscn-vX.X.X-XXXXX-amd64.tar.gz
x kscn-XXXXX-amd64/
x kscn-XXXXX-amd64/conf/
x kscn-XXXXX-amd64/conf/kscnd.conf
x kscn-XXXXX-amd64/bin/
x kscn-XXXXX-amd64/bin/kscnd
x kscn-XXXXX-amd64/bin/kscn
```

편의상 바이너리 경로를 $PATH로 추가하겠습니다. 여러분의 노드에서는 실제 경로를 사용하세요.

```console
$ export PATH=$PATH:~/path/to/kscn-XXXXX-amd64/bin
```

SCN은 RHEL, CentOS와 Fedora와 같은 다양한 RPM 배포판을 제공합니다. 더 자세한 내용은 [Installation](/content/installation-guide/deployment/service-chain/references/scn/installation)를 참조하십시오.

```console
$ curl -o /etc/yum.repos.d/klaytn.repo https://packages.klaytn.net/config/rhel/7/prod.repo
  % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed
     100 118 100 118 0 0 1113 0 --:--:-- --:--:-- --:--:-- 1102 

$ yum list | grep klaytn 
packages-klaytn-prod 31 kB/s | 2.9 kB 00:00 
homi.x86_64           v1.8.0-0.el7      packages-klaytn-prod 
kbnd.x86_64           v1.8.0-0.el7      packages-klaytn-prod 
kcnd.x86_64           v1.8.0-0.el7      packages-klaytn-prod 
kcnd-baobab.x86_64    v1.8.0-0.el7      packages-klaytn-prod 
kend.x86_64           v1.8.0-0.el7      packages-klaytn-prod 
kend-baobab.x86_64    v1.8.0-0.el7      packages-klaytn-prod 
kgen.x86_64           v1.8.0-0.el7      packages-klaytn-prod 
kpnd.x86_64           v1.8.0-0.el7      packages-klaytn-prod 
kpnd-baobab.x86_64    v1.8.0-0.el7      packages-klaytn-prod 
kscnd.x86_64          v1.8.0-0.el7      packages-klaytn-prod 
ksend.x86_64          v1.8.0-0.el7      packages-klaytn-prod 
kspnd.x86_64          v1.8.0-0.el7      packages-klaytn-prod 

$ yum install kscnd
```

### 1 단계: genesis.json 및 nodekey 생성 <a href="#step-1-create-genesis-json-and-a-key" id="step-1-create-genesis-json-and-a-key"></a>

homi 유틸리티를 사용해 필요한 파일을 생성할 것입니다. `homi`는 클레이튼 블록체인의 환경설정을 위해 필요한 스크립트, 환경설정 파일 그리고 프라이빗 키들을 자동으로 생성하는 유틸리티입니다. Linux와 Mac PC 모두에서 homi를 실행할 수 있습니다.

먼저 다운로드 한 homi 아카이브를 추출하십시오.

```console
$ tar xvf homi-vX.X.X-XXXXX-amd64.tar.gz
x homi-XXXXX-amd64/
x homi-XXXXX-amd64/bin/
x homi-XXXXX-amd64/bin/homi
```

`bin` 폴더로 가서 파일 생성을 위해 다음의 옵션과 함께 `homi`를 실행하세요. `homi setup --gen-type local --cn-num 4 --test-num 1 --servicechain --chainID 1002 --p2p-port 22323 -o homi-output` Since Baobab's `chainID` is 1001, for convenience, the `chainID` of the ServiceChain constructed in this example is set to 1002. 실제 서비스를 출시하기 위해 블록체인을 운영하는 경우, 다른 서비스 체인과 겹치지 않도록 <https://chainlist.defillama.com/에서> 새로운 chainID를 등록한 뒤에 사용할 것을 권장합니다. 서비스체인의 포트는 기본값이 22323으로 설정되어 있습니다.

```console
$ ./homi setup --gen-type local --cn-num 4 --test-num 1 --servicechain --chainID 1002 --p2p-port 22323 -o homi-output
Created :  homi-output/keys/passwd1
Created :  homi-output/keys/passwd2
Created :  homi-output/keys/passwd3
Created :  homi-output/keys/passwd4
Created :  homi-output/scripts/genesis.json
Created :  homi-output/keys/nodekey1
Created :  homi-output/keys/validator1
Created :  homi-output/keys/nodekey2
Created :  homi-output/keys/validator2
Created :  homi-output/keys/nodekey3
Created :  homi-output/keys/validator3
Created :  homi-output/keys/nodekey4
Created :  homi-output/keys/validator4
Created :  homi-output/scripts/static-nodes.json
Created :  homi-output/keys_test/testkey1
Created :  homi-output/keys_test/keystore1/0xdC7218621513f71d609653d22C39d79d558d9CDC
Created :  homi-output/Klaytn.json
Created :  homi-output/Klaytn_txpool.json
```

결과물 중 다음 단계에서 우리가 사용할 파일은 `nodeky*`, `genesis.json` 그리고 `static-nodes.json`입니다.

### 2 단계: static-nodes.json 수정 <a href="#step-2-customize-static-nodes-json" id="step-2-customize-static-nodes-json"></a>

문서 편집기에서 `homi-output/scripts/static-nodes.json`를 열고 IP 주소 및 포트를 여러분 노드의 실제 값으로 업데이트 해주세요. 이 예제에서는 서비스체인의 각 SCN 노드의 IP가 아래 그림과 같다고 가정합니다. 여러분이 여기에 설정한 포트값은 4 단계에서 사용될 것이므로 꼭 기억해주세요.

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-f3f2176dc7496c2884cc5a3bb58d6e819f48754b%2Fsc-4scn-ip.png?alt=media)

```json
[
     "kni://38693ad4b17ff77...23153@192.168.0.1:22323?discport=0\u0026ntype=cn",
     "kni://f36d969b16f7337...1329b@192.168.0.2:22323?discport=0\u0026ntype=cn",
     "kni://16e55d8921ab034...b2bec@192.168.0.3:22323?discport=0\u0026ntype=cn",
     "kni://0973e792a421c1d...bbd71@192.168.0.4:22323?discport=0\u0026ntype=cn"
]
```

`static-nodes.json`을 업데이트한 후, 결과 폴더(`homi-output`)를 모든 SCN에 업로드하세요. 이 예제에서는 SCN-L2-01, SCN-L2-02, SCN-L2-03, SCN-L2-04 노드입니다.

```console
$ scp -r path/to/homi-output/ user@192.168.0.1:~/
$ scp -r path/to/homi-output/ user@192.168.0.2:~/
$ scp -r path/to/homi-output/ user@192.168.0.3:~/
$ scp -r path/to/homi-output/ user@192.168.0.4:~/
```

### 3 단계: 노드 초기화 <a href="#step-3-node-initialization" id="step-3-node-initialization"></a>

이제 제네시스 파일을 사용해서 각 노드를 초기화해보겠습니다. 개별 노드에서 아래의 명령을 실행합니다. 홈 디렉토리에 체인 데이터와 로그를 저장하는 데이터 폴더를 생성합니다. `--datadir` 지시문을 이용해 데이터 폴더를 변경할 수 있습니다. 이 예제에서 우리는 데이터 폴더를 `\~/data`에 지정했습니다.

```console
$ kscn --datadir ~/data init ~/homi-output/scripts/genesis.json

$ ls ~/data
keystore    klay        kscn
```

### 4 단계: `nodekey` 및 `static-nodes.json` 설치 <a href="#step-4-install-nodekey" id="step-4-install-nodekey"></a>

모든 SCN에서 `static-nodes.json`을 데이터 폴더에 복사하세요.

```console
$ cp ~/homi-output/scripts/static-nodes.json ~/data/
```

1 단계에서 우리는 4개의 노드키(nodekey)를 생성했습니다. 각각의 노드키를 SCN에 할당한 뒤, 매칭되는 `nodekey`를 각각 SCN 데이터 폴더에 복사하세요. 예를 들어 SCN-L2-01(192.168.0.1) 노드에는 `nodekey1`를 SCN-L2-02(192.168.0.2), SCN-L2-03(192.168.0.3) 그리고 SCN-L2-04(192.168.0.4)에는 `nodekey2`, `nodekey3`와 `nodekey4`를 각각 사용합니다.

```console
$ cp ~/homi-output/keys/nodekey{1..4} ~/data/klay/nodekey
```

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-81543e32267d9cf5c8d9c3908340ae52017e4de5%2Fsc-4scn-nodekey.png?alt=media)

### 5 단계: 노드 설정 <a href="#step-5-configure-nodes" id="step-5-configure-nodes"></a>

모든 SCN에서 kscn 설치 폴더로 이동하여 `conf/kscnd.conf`를 다음과 같이 편집하세요. `PORT`는 `homi`를 설치하는 데 사용하는 포트이며, `SC_SUB_BRIDGE`는 다음 장에서 브릿지를 연결하는 데 필요합니다. 현재는 0으로 설정하겠습니다. `DATA_DIR`에서 3 단계에 설정한 데이터 폴더를 입력합니다.

```
...
PORT=22323
...
SC_SUB_BRIDGE=0
...
DATA_DIR=~/data
...
```

### 6 단계: 노드 시작 <a href="#step-6-start-nodes" id="step-6-start-nodes"></a>

모든 SCN에서 다음 명령을 실행하세요.

```console
$ kscnd start
Starting kscnd: OK
```

`klay.blockNumber`를 보면서 블록 생성 상태를 확인할 수 있습니다. 조회 결과가 0이 아니라면 노드가 제대로 작동하는 것입니다.

```console
$ kscn attach --datadir ~/data
> klay.blockNumber
10
```

노드를 중지하고 싶으면 `kscnd stop` 명령을 사용할 수 있습니다.

### (예) 토큰 전송 트랜잭션 생성 및 확인 <a href="#example-creation-and-confirmation-of-a-value-transfer-transaction" id="example-creation-and-confirmation-of-a-value-transfer-transaction"></a>

이제 4개의 노드로 구성된 서비스체인이 작동하고 있습니다. 서비스체인이 잘 동작하는지 확인하기 위해 서비스체인에서 토큰 전송 트랜잭션을 실행해 보겠습니다.

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-c4a3d2bc004b16501505a67fbe7284b928563bda%2Fsc-4scn-test.png?alt=media)

#### 1 단계: 테스트 계정 가져오기 <a href="#step-1-import-the-test-account" id="step-1-import-the-test-account"></a>

`testkey1`는 1 단계에서 `homi`를 통해 자동으로 생성되었습니다. `homi`에 의해 생성된 `genesis.json`에 설명되어 있듯, KLAY는 테스트 계정에 지급되어 있습니다.

```console
$ kscn account import --datadir ~/data ~/homi-output/keys_test/testkey1
Your new account is locked with a password. Please give a password. Do not forget this password.
Passphrase:
Repeat passphrase:
Address: {80119c31cdae67c42c8296929bb4f89b2a52cec4}
```

#### 2 단계: 계정 잠금 해제 <a href="#step-2-unlock-the-account" id="step-2-unlock-the-account"></a>

계정의 잠금 해제는 `testkey1`를 가져온 SCN의 콘솔을 통해서만 가능합니다.

```console
$ kscn attach --datadir ~/data
> personal.unlockAccount("80119c31cdae67c42c8296929bb4f89b2a52cec4")
Unlock account 80119c31cdae67c42c8296929bb4f89b2a52cec4
Passphrase:
true
```

#### 3 단계: 트랜잭션을 보내고 잔액 확인하기 <a href="#step-3-send-a-transaction-and-check-the-balance" id="step-3-send-a-transaction-and-check-the-balance"></a>

```console
> klay.sendTransaction({from: "80119c31cdae67c42c8296929bb4f89b2a52cec4", to: "305c6cc464d5fe1e624679695a20d641a01688e1", value: 10})
"0xa0e7102e8f14200cec8d964aacc1c9ed7c22271078b2b213170c64333cbca8a3"
> klay.getBalance("305c6cc464d5fe1e624679695a20d641a01688e1")
10
```

{% hint style="info" %}
가장 단순한 형태의 서비스 체인은 SCN를 하나만 가지고 있는 것입니다. 이 예제에서는 4개 노드를 가진 서비스 체인을 설명했습니다. 하지만 필요에 따라 단일 노드 서비스 체인도 구축할 수 있습니다. 1 단계 'genesis.json 및 nodekeys 생성하기'에서 `--cn-num 4` 대신 `--cn-num 1`를 homi에 전달하면 됩니다.

비잔틴 장애를 견뎌내기 위해서는 최소 4개의 노드가 필요합니다. BTF 알고리즘 하에서 높은 가용성을 보장하기 위한 SCN의 최소값은 4입니다. 2개의 SCN인 경우 하나에 장애가 생길 경우 다른 하나가 혼자서 합의를 이루지 못하기 때문에 가용성을 보장하지 못 합니다.
{% endhint %}


# Connecting to Baobab

이 장에서는 4개 노드 서비스체인을 Baobab 네트워크에 연결하는 방법을 설명합니다. Baobab EN을 구축하고 여러분의 SCN 중 하나와 연결할 것입니다. 그리고 나서 서비스체인의 블록 정보를 Baobab 네트워크에 저장하는 앵커링 기능을 사용해 볼 것입니다.

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-4b325bd195c64bf6d1895ea0aec48f7135190aa2%2Fsc-en-scn-arch.png?alt=media)

### Prerequisites <a href="#prerequisites" id="prerequisites"></a>

* EN용 Linux 또는 MacOS 서버 1대
* 테스트를 위한 최소 하드웨어 요구 사항
  * CPU: 4-core (Intel Xeon or equivalent), RAM: 16GB, HDD: 50GB
  * 자세한 설명은 [시스템 요구사항](/content/installation-guide/deployment/service-chain/references/system-requirements)을 참조하세요.
* Baobab EN 실행파일을 다운로드하세요. For the full list of downloadable binaries, see [Download](/content/installation-guide/deployment/download).
* 가정 및 제약
  * 서비스 체인이 설치되어 실행 중입니다. 네트워크를 설치하기 위해서는 [4개 노드 서비스 체인 설치하기](/content/installation-guide/deployment/service-chain/getting-started/4nodes-setup-guide)를 참고해주세요.
  * Baobab EN.
  * 오직 일대일 연결만 지원되기 때문에 하나의 EN은 하나의 SCN에 연결될 수 있습니다.
  * 모든 SCN이 EN과 연결되어야 하는 것은 아닙니다.

### 0 단계 : Baobab EN 설치하기 <a href="#install-baobab-en" id="install-baobab-en"></a>

The installation is the uncompression of the downloaded package. EN 서버에 EN 패키지를 압축 해제합니다.

```bash
EN-01$ tar xvf ken-baobab-vX.X.X-XXXXX-amd64.tar.gz
```

### 1 단계 : genesis.json 준비하기 <a href="#step-1-preparing-genesis-json" id="step-1-preparing-genesis-json"></a>

EN 서버에서 아래 명령어로 `Baobab` 네트워크를 위한 `genesis.json`을 다운로드하세요.

```
EN-01$ curl -X GET https://packages.klaytn.net/baobab/genesis.json -o ~/genesis.json
```

### 2 단계 : EN 노드 초기화 <a href="#step-2-en-node-initialization" id="step-2-en-node-initialization"></a>

다운로드 받은 제네시스 파일을 사용해서 EN을 초기화합니다. 아래의 명령어를 실행하시면, It will create the data folder storing the chain data and logs on your home directory. You can change the data folder using the `--datadir` directive.

```
EN-01$ ken init --datadir ~/data ~/genesis.json
```

### 3 단계 : EN 노드 설정 <a href="#step-3-configure-the-en-node" id="step-3-configure-the-en-node"></a>

ken 설치 폴더에서 `mv kend_baobab.conf kend.conf` 명령어로 파일명을 변경하고, `conf/kend.conf` 파일을 아래와 같이 수정하세요.

```
...
NETWORK="baobab"
...
SC_MAIN_BRIDGE=1
...
DATA_DIR=~/data
...
```

### 4 단계 : EN 노드 시작 <a href="#step-4-start-the-en-node" id="step-4-start-the-en-node"></a>

```
EN-01$ kend start
Starting kscnd: OK
```

EN 노드를 시작하고, 콘솔에서 klay.blockNumber를 조회하면 블록 동기화 상태를 확인할 수 있습니다. If this number is not 0, the node is working fine. Downloading all blocks on the Baobab network may take a long time depending on network conditions and hardware performance, so we recommend using [Fast Sync](/content/installation-guide/deployment/endpoint-node/installation-guide/configuration) to synchronize blocks.

```
EN-01$ ken attach --datadir ~/data
> klay.blockNumber
21073
```

노드를 중지하려면 `kend stop` 명령어를 사용하세요.

### 5 단계 : EN 노드의 KNI 확인 <a href="#step-5-check-kni-of-en-node" id="step-5-check-kni-of-en-node"></a>

SCN-L2-01 노드에서 연결하는 데 사용되는 정보인 EN-01의 KNI를 잘 기억해 둡니다. 이 정보는 다음 단계에서 main-bridges.json을 생성할 때 사용됩니다.

```
EN-01$ ken attach --datadir ~/data
> mainbridge.nodeInfo.kni
"kni://0f7aa6499553...25bae@[::]:50505?discport=0"
```

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-37925eabc31cc38cf921e097cf07e52ccff744a0%2Fsc-en-scn-nodeInfo.png?alt=media)

### 6 단계 : main-bridges.json 생성 <a href="#step-6-create-main-bridges-json" id="step-6-create-main-bridges-json"></a>

SCN-L2-01(참고: EN-01 아님)에 로그온하고 `~/data`에 `main-bridges.json`을 만듭니다. `@` 문자 뒤에 있는 `[::]`를 EN-01의 IP 주소로 바꿉니다.

```
SCN-L2-01$ echo '["kni://0f7aa6499553...25bae@192.168.1.1:50505?discport=0"]' > ~/data/main-bridges.json
```

### Step 7: Configure SCN then Restart kscn <a href="#step-7-configure-scn-then-restart-kscn" id="step-7-configure-scn-then-restart-kscn"></a>

SCN-L2-01의 콘솔에서 `kscn-XXXXX-amd64/conf/kscnd.conf`를 편집합니다. `SC_SUB_BRIDGE`가 1로 설정되면, SCN-L2-01에서 kscn이 실행될 때 데이터 앵커링이 자동으로 동작합니다. 이 예제에서는 `SC_PARENT_CHAIN_ID`는 부모체인인 Baobab의 `chainID`가 1001이기 때문에 1001로 설정되어 있습니다. `SC_ANCHORING_PERIOD`는 앵커링 tx를 메인체인으로 보낼 주기를 결정하는 파라미터입니다. 값을 10으로 설정하면 10블록마다 앵커링을 수행하도록 노드를 구성합니다. 기본값은 1입니다.

```
...
SC_SUB_BRIDGE=1
...
SC_PARENT_CHAIN_ID=1001
...
SC_ANCHORING_PERIOD=10
...
```

다음 명령어로 kscn을 다시 시작합니다.

```
SCN-L2-01$ kscnd stop
Shutting down kscnd: Killed
SCN-L2-01$ kscnd start
Starting kscnd: OK
```

SCN-L2-01과 EN-01이 연결되었는지를 확인하기 위해서 `subbridge.peers.length`을 조회해 봅니다.

```
SCN-L2-01$ kscn attach --datadir ~/data
> subbridge.peers.length
1
```

### 앵커링 <a href="#anchoring" id="anchoring"></a>

EN-01 및 SCN-L2-01 연결을 완료한 후 앵커링을 통해 상위 체인에 ServiceChain 블록 정보를 기록할 수 있습니다. 이번 예제에서는 부모체인의 운영자 계정을 충전하고 앵커링을 활성화하고 앵커링된 블록 번호를 확인합니다.

#### 1 단계 : 앵커링 테스트를 위한 KLAY 얻기 <a href="#step-1-get-klay-to-test-anchoring" id="step-1-get-klay-to-test-anchoring"></a>

앵커링을 사용하려면 SCN-L2-01이 Baobab에 대한 앵커링 트랜잭션을 전송해야 합니다. 따라서 `subbridge.parentOperator` 계정에는 거래 수수료를 지불하기에 충분한 KLAY가 있어야 합니다. [Baobab Wallet Faucet](https://baobab.wallet.klaytn.foundation/)에서 일부 KLAY를 가져오고 일부 KLAY를 `parentOperator`로 전송합니다. 실제 서비스 환경에서 데이터 앵커링을 하려면 `parentOperator`에 거래 수수료에 대한 충분한 KLAY가 있어야 합니다.

```
SCN-L2-01$ kscn attach --datadir ~/data
> subbridge.parentOperator
"0x3ce216beeafc62d20547376396e89528e1d778ca"
```

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-5845201c07f0fa9c0655423d6f8c77ffac87f1ea%2Fsc-en-scn-faucet.png?alt=media)

#### 2 단계 : 앵커링 시작 <a href="#step-2-start-anchoring" id="step-2-start-anchoring"></a>

엥커링을 시작하기 위해서는 다음의 명령어를 수행합니다.

```
SCN-L2-01$ kscn attach --datadir ~/data
> subbridge.anchoring(true)
true
```

앵커링이 시작된 후 `subbridge.latestAnchoredBlockNumber`를 사용하여 Baobab에 가장 최근에 앵커된 블록을 확인할 수 있습니다. 최근 앵커링된 블록을 확인하기 위해서는 EN이 Baobab 네트워크의 최신 블록으로 동기화된 이후에만 가능하다는 점에 유의하십시오. 기본적으로 SCN-L2-01은 앵커링이 활성화된 이후부터 모든 블록에 대해서 앵커링을 시도합니다. 앵커링 주기는 `SC_ANCHORING_PERIOD`를 변경하여 설정할 수 있습니다. 예를 들면 값이 10으로 설정되면 블록 번호가 10의 배수일 때마다 앵커링을 시도합니다.

```
SCN-L2-01$ kscn attach --datadir ~/data
> subbridge.latestAnchoredBlockNumber
100
```

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-f95f330644af7028018dabaaf657939191485971%2Fsc-en-scn-anchoring.png?alt=media)


# 크로스체인 토큰 전송

이번 장에서는 Baobab 네트워크와 서비스체인 간에 토큰을 전송하는 방법을 설명합니다. 운영자 계정에 KLAY를 확보하고 브릿지 컨트랙트 및 ERC-20 컨트랙트를 배포합니다. 그런 다음 SCN 서브 브릿지에 계약 주소를 등록합니다. 그리고 ERC-20 토큰 전송을 테스트합니다.

### Prerequisites <a href="#prerequisites" id="prerequisites"></a>

* 서비스체인을 구성하고, [Baobab 연결](/content/installation-guide/deployment/service-chain/getting-started/en-scn-connection)의 설명에 따라 서비스체인을 Baobab EN에 연결했다고 가정합니다.
* [servicechain-value-transfer-examples](https://github.com/klaytn/servicechain-value-transfer-examples) 저장소를 복제합니다.
* `Node.js` (v14)과 `npm`을 설치합니다. ([How to install](https://nodejs.org/en/download/package-manager/))
  * 이번 예제에서는 v14를 지원하는 axios 및 caver-js를 사용합니다.

### ERC-20 Token Transfer (one-step) <a href="#erc-20-token-transfer-onestep" id="erc-20-token-transfer-onestep"></a>

#### 1 단계 : 운영자 계정에 KLAY 추가하기 <a href="#step-1-add-klay-to-the-operator-accounts" id="step-1-add-klay-to-the-operator-accounts"></a>

SCN에 연결하여 `subbridge.parentOperator`와 `subbridge.childOperator`를 실행하여 계정 주소를 확인하세요.

```
$ kscn attach --datadir ~/data
> subbridge.childOperator
"0x10221f7f9355017cd0c11444e7eecb99621bacce"
> subbridge.parentOperator
"0x3ce216beeafc62d20547376396e89528e1d778ca"
```

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-0f35dd64b964f1a3ea17c0b700a66ce9d547e542%2Fsc-vt-add-klay.png?alt=media)

`subbridge.parentOperator` 및 `subbridge.childOperator`에는 트랜잭션을 보내기에 충분한 KLAY가 있어야 합니다. `subbridge.parentOperator`는 Baobab 네트워크의 계정이고 `subbridge.childOperator`는 ServiceChain 네트워크의 계정입니다. [Baobab Wallet](https://baobab.wallet.klaytn.foundation/)에서 테스트 계정을 만들고 faucet에서 테스트 KLAY를 받으세요. 그런 다음 일부 KLAY를 `parentOperator`에 전송합니다. `childOperator`는 `homi`가 생성한 테스트 계정에서 KLAY를 가져와야 합니다([EN 설정 및 SCN 연결 가이드 참조](/content/installation-guide/deployment/service-chain/getting-started/en-scn-connection)).

```
$ kscn account import ~/homi-output/keys_test/testkey1
Your new account is locked with a password. Please give a password. Do not forget this password.
Passphrase:
Repeat passphrase:
Address: {80119c31cdae67c42c8296929bb4f89b2a52cec4}
```

```
$ kscn attach --datadir ~/data
> personal.unlockAccount("80119c31cdae67c42c8296929bb4f89b2a52cec4")
Unlock account 80119c31cdae67c42c8296929bb4f89b2a52cec4
Passphrase:
True
> klay.sendTransaction({from:"80119c31cdae67c42c8296929bb4f89b2a52cec4", to:subbridge.childOperator, value: web3.toPeb(1000, "KLAY")})
"0x84caab84ebf0c4bb4ecf0a7849f1de3e479f1863a95f70c51047a7ca7bc64b33"
```

운영자 계정에 충분한 잔액이 있는지 확인하십시오. 서브브릿지가 설치된 SCN 노드의 콘솔에서 다음과 같이 조회할 수 있습니다.

```
> klay.getBalance(subbridge.childOperator)
1e+21
> subbridge.childOperatorBalance
1e+21
> subbridge.parentOperatorBalance
1e+18
```

#### 2 단계 : 컨트랙트 배포 <a href="#step-2-deploy-contracts" id="step-2-deploy-contracts"></a>

* SCN에 연결하여 컨트랙트 배포를 위한 노드 환경을 준비합니다. Clone the repository [servicechain-value-transfer-examples](https://github.com/klaytn/servicechain-value-transfer-examples).

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-c288206ca175d417d5dbceff29cda32af3cbac14%2Fsc-vt-deploy.png?alt=media)

이 단계에서는 브리지 컨트랙트와 토큰 컨트랙트를 부모 체인과 자식 체인에 모두 배포합니다. 토큰 컨트랙트는 발행/전송 테스트를 위한 것이고 브리지 컨트랙트는 토큰 전송 요청을 수신/처리하는데 사용됩니다.

```bash
$ git clone https://github.com/klaytn/servicechain-value-transfer-examples
$ cd servicechain-value-transfer-examples
$ npm install
$ cd erc20
```

텍스트 편집기에서 아래와 같이 `bridge_info.json`을 수정합니다.

* `child` 부분(ServiceChain 네트워크의 SCN 노드)에 있는 `url`을 SCN 노드 IP와 `kscnd.conf`에 있는 `RPC_PORT`의 포트 번호로 바꾸십시오.
* `child.key`를 `homi`가 생성한 `testkey1`로 교체합니다.
* `child.operator`를 이전 단계에서 조회한 `subbridge.childOperator` 주소로 설정합니다.
* `parent` 부분(Baobab 네트워크의 EN 노드)에 있는 `url`을 EN 노드 IP와 `kend.conf`의 `RPC_PORT`에 있는 포트 번호로 바꾸십시오.
* `parent.key`를 이전 단계에서 [Baobab Wallet](https://baobab.wallet.klaytn.foundation/)에서 생성한 테스트 계정의 개인 키로 대체합니다.
* `parent.operator`를 이전 단계의 `subbridge.parentOperator`로 설정합니다.

```
{
     "child" : {
         "url": "http://192.168.0.1:7551",
         "key": "0x66cb283353589a10866b58d388e9d956e5a9c873a8c78fa4411d460c19c494ea",
         "operator": "0x10221f7f9355017cd0c11444e7eecb99621bacce"
     },
     "parent" : {
         "url": "http://192.168.0.5:8551",
         "key": "0x26f4b5ac42ceabcfd3b23a991fdbfc792d10ce700a99582fdf9185a8f163b790",
         "operator": "0x3ce216beeafc62d20547376396e89528e1d778ca"
     }
 }
```

`node erc20-deploy.js`를 실행하여 토큰 컨트랙트를 배포합니다. 이 스크립트는 브리지 컨트랙트과 토큰 컨트랙트를 모두 배포하고 브릿지 쌍을 초기화하기 위한 API 사용법을 출력해 줍니다.

```
$ node erc20-deploy.js
------------------------- erc20-deploy START -------------------------
> info.bridge: 0xEa024d8101E112330f2d7B1a7e7932034E206721
> info.token: 0xbE641028610F628835C36F12bE62d54d74308D70
> info.bridge: 0xA5af6Ffe13b367626B5AdF827DdE7438E3Db4463
> info.token: 0x52F8Fa79Fa6D37b18b7AC8f9Ca835373f3C9270f
> subbridge.registerBridge("0xEa024d8101E112330f2d7B1a7e7932034E206721", "0xA5af6Ffe13b367626B5AdF827DdE7438E3Db4463")
> subbridge.subscribeBridge("0xEa024d8101E112330f2d7B1a7e7932034E206721", "0xA5af6Ffe13b367626B5AdF827DdE7438E3Db4463")
> subbridge.registerToken("0xEa024d8101E112330f2d7B1a7e7932034E206721", "0xA5af6Ffe13b367626B5AdF827DdE7438E3Db4463", "0xbE641028610F628835C36F12bE62d54d74308D70", "0x52F8Fa79Fa6D37b18b7AC8f9Ca835373f3C9270f")
------------------------- erc20-deploy END -------------------------
```

#### Step 3: Token transfer <a href="#step-3-token-transfer" id="step-3-token-transfer"></a>

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-1ee40038caed76732be4a5477a2471d7544dd14d%2Fsc-vt-transfer.png?alt=media)

`node erc20-transfer-1step.js`명령을 실행하여 토큰을 전송합니다. ERC-20 토큰 컨트랙트의 구현을 수정하여 한번의 호출로(one-step) 토큰 전송이 가능합니다. 토큰 컨트랙트의 수정을 원하지 않거나 이미 배포된 토큰 컨트랙트가 있는 경우 [ERC-20 Token Transfer (two-step)](#erc-20-token-transfer-twostep)을 참조하십시오.

```
$ node erc20-transfer-1step.js
------------------------- erc20-transfer-1step START -------------------------
alice balance: 0
requestValueTransfer..
alice balance: 100
------------------------- erc20-transfer-1step END -------------------------
```

결과가 `alice balance: 100`이면 성공적으로 실행된 것입니다.

### ERC-20 Token Transfer (two-step) <a href="#erc-20-token-transfer-twostep" id="erc-20-token-transfer-twostep"></a>

2번의 호출로 토큰 전송하기 위해 <0>erc20-transfer-2step.js\</0>를 실행합니다. 2번의 호출로 토큰 전송하는 예는 ERC-20 토큰 컨트랙트를 수정하지 않고 그대로 사용합니다. 먼저 (1) 브릿지 컨트랙트를 승인한 다음 (2) 컨트랙트 함수인 `requestERC20Transfer()`를 호출하는 단계로 구성됩니다. 브릿지 및 토큰 컨트랙트를 이미 배포했으므로 이번 단계에서는 컨트랙트를 배포하지 않습니다. 만약 컨트랙트를 배포하지 않은 경우 먼저 컨트랙트 배포를 진행해야 합니다. `node erc20-deploy.js`명령으로 계약을 배포할 수 있습니다.

```
$ node erc20-transfer-2step.js
> ------------------------- erc20-transfer-2step START -------------------------
> alice balance: 100
> requestValueTransfer..
> alice balance: 200
------------------------- erc20-transfer-2step END -------------------------
```

### KIP-7 Token Transfer via ERC-20 Interface (two-step) <a href="#kip-7-token-transfer-via-erc-20-interface-two-step" id="kip-7-token-transfer-via-erc-20-interface-two-step"></a>

KIP-7은 ERC-20과 호환되는 토큰 표준입니다. KIP-7 토큰 컨트랙트의 `requestERC20Transfer()` 함수를 호출하여 부모 체인과 자식 체인 간에 KIP-7 토큰을 전송할 수 있습니다. ERC-20 인터페이스를 통해 KIP-7 토큰을 전송하는 경우, 브릿지가 트랜잭션 발신자를 대신하여 토큰을 보낼 수 있도록 `approve()` 함수를 호출합니다. 그런 다음 `requestERC20Transfer()` 함수를 호출합니다. 아래 명령으로 브릿지 컨트랙트와 KIP-7 컨트랙트를 배포합니다.

```
$ node kip7-deploy.js
> ------------------------- kip7-deploy START -------------------------
> info.bridge: 0x04e929Cd2A08acd28a210369407D8Ca237Edd8FE
> info.token: 0xE0E2fC6C7d1eB069153E0c12a4C87B01586b39e7
> info.bridge: 0xEb502159A4B4E876B1cb423f250DCC0d276e01b6
> info.token: 0xd4f02Ca1d49674056A9ec78fbBDc9e1e97726A4F
> subbridge.registerBridge("0x04e929Cd2A08acd28a210369407D8Ca237Edd8FE", "0xEb502159A4B4E876B1cb423f250DCC0d276e01b6")
> subbridge.subscribeBridge("0x04e929Cd2A08acd28a210369407D8Ca237Edd8FE", "0xEb502159A4B4E876B1cb423f250DCC0d276e01b6")
> subbridge.registerToken("0x04e929Cd2A08acd28a210369407D8Ca237Edd8FE", "0xEb502159A4B4E876B1cb423f250DCC0d276e01b6", "0xE0E2fC6C7d1eB069153E0c12a4C87B01586b39e7", "0xd4f02Ca1d49674056A9ec78fbBDc9e1e97726A4F")
------------------------- kip7-deploy END -------------------------
```

아래 명령어는 `requestERC20Transfer()`와 함께 ERC-20 인터페이스를 사용하여 KIP-7 토큰을 보내는 예제입니다.

```
$ node kip7-transfer-2step-erc20-interface.js
> ------------------------- kip7-transfer-2step-erc20-interface START -------------------------
> alice balance: 0
> requestValueTransfer..
> alice balance: 100
> ------------------------- kip7-transfer-2step-erc20-interface END -------------------------
```

[service-chain-value-transfer-example](https://github.com/klaytn/servicechain-value-transfer-examples)을 참조하십시오.

### Native Support for KIP-7 and KIP-17 (To Be Implemented) <a href="#native-support-for-kip-7-and-kip-17-to-be-implemented" id="native-support-for-kip-7-and-kip-17-to-be-implemented"></a>

현재 Klaytn 팀에서 제공하는 브릿지 컨트랙트는 토큰 전송을 위해 `requestERC20Transfer()` 및 `requestERC721Transfer()`만 지원합니다. KIP-7 및 KIP-17에 대한 기능은 곧 지원될 예정입니다. 구현이 완료되기 까지는 위의 설명과 같이 ERC-20 인터페이스를 사용하여 KIP-7 토큰을 전송할 수 있습니다.

### ERC-721, KIP-17와 KLAY 토큰 전송 <a href="#value-transfer-for-erc721-kip17-and-klay" id="value-transfer-for-erc721-kip17-and-klay"></a>

ERC-721, KIP-17, KLAY의 동작도 위와 동일합니다. [`erc721`](https://github.com/klaytn/servicechain-value-transfer-examples/tree/main/erc721), [`kip17`](https://github.com/klaytn/servicechain-value-transfer-examples/tree/main/kip17), and [`klay`](https://github.com/klaytn/servicechain-value-transfer-examples/tree/main/klay) directories contain corresponding example source code.


# HA(High Availability) for ServiceChain

ServiceChain에서 하나의 브리지만 사용하는 경우, 해당 브리지가 단일 실패 지점이 될 수 있습니다. 이를 해결하기 위해 두 개 이상의 브리지로 고가용성 시스템을 구축하는 방법을 설명합니다. 아래 그림과 같이 최소 두개 이상의 브릿지가 연결되어 있다면, 한 브릿지가 연결 상 문제가 있다고 하더라도 다른 브릿지를 통해 체인간 데이터 앵커링 및 토큰 전송이 정상적으로 수행될 수 있습니다.

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-9dc7b2786476900684787ec2ecb6288117a40cdb%2Fsc-ha-arch.png?alt=media)

### Prerequisites <a href="#prerequisites" id="prerequisites"></a>

* EN의 메인 브릿지와 SCN의 서브 브릿지가 연결되어 있습니다. If it's not, please refer to [Baobab connection](/content/installation-guide/deployment/service-chain/getting-started/en-scn-connection) to establish the connection.
* 이번 섹션에서는 Baobab과 ServiceChain 사이에 추가로 브릿지를 하나 더 연결하는 방법을 설명합니다. <0>Baobab 연결\</0>과 같은 방법으로 브리지를 하나 더 추가하여 HA를 구성할 수 있습니다.

### 1단계: EN-SCN 간에 다른 브릿지 추가 <a href="#step-1-adding-another-bridge-between-en-scn" id="step-1-adding-another-bridge-between-en-scn"></a>

In [Connecting to Baobab](/content/installation-guide/deployment/service-chain/getting-started/en-scn-connection), we assume that the EN and the SCN connected by a bridge as EN-01 and SCN-L2-01, respectively. 이번 섹션에서는 EN-02와 SCN-L2-02 사이에 또 다른 브릿지를 추가합니다. 이전과 동일한 절차로 진행되므로 여기서는 간단히 설명합니다.

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-4cde1ff445017171bd59b1d00753c0028dda8176%2Fsc-ha-add-bridge.png?alt=media)

EN-02의 `conf/kend.conf` 파일에서 `SC_MAIN_BRIDGE`을 1로 설정하고, ken을 다시 시작합니다.

```console
SC_MAIN_BRIDGE=1
```

다음 명령어로 EN-02의 KNI 정보를 확인합니다.

```console
EN-02$ ken attach --datadir ~/data
> mainbridge.nodeInfo.kni
"kni://eb8f21df10c6562...25bae@[::]:50505?discport=0"
```

SCN-L2-02에 접속한 후 EN-02의 KNI 정보로 `main-bridges.json` 파일을 만듭니다. 해당 파일은 대괄호 속에 KNI 정보가 있는 형식이라는 점에 주의해야 합니다.

```console
SCN-L2-02$ echo '["kni://eb8f21df10c6562...25bae@192.168.0.5:50505?discport=0"]' > ~/data/main-bridges.json
```

아래와 같이 SCN-L2-02의 셸에서 `kscn-XXXXX-amd64/conf/kscnd.conf` 파일을 편집합니다. 브리지를 활성화하려면 `SC_SUB_BRIDGE`를 1로 설정합니다. `SC_PARENT_CHAIN_ID`는 Baobob의 `chainID 1001`로 설정합니다. `SC_ANCHORING_PERIOD`는 부모 체인(Baobab)으로 앵커링 트랜잭션을 보낼 주기를 설정하는 매개변수입니다. 이 예제에서 앵커 트랜잭션은 10개의 자식 블록마다 부모 체인(Baobab)으로 전송됩니다.

```
...
SC_SUB_BRIDGE=1
...
SC_PARENT_CHAIN_ID=1001
...
SC_ANCHORING_PERIOD=10
...
```

EN-02에서 ken을 다시 시작하면, EN-02과 SCN-L2-02 사이에 브릿지가가 자동으로 연결되고, 브릿지가 연결된 지점부터 데이터 앵커링이 시작됩니다.

EN-02와 SCN-L2-02 사이에 브릿지가 추가되어, 아래 그림과 같이 두 노드 사이에 브릿지로 연결된 것을 볼 수 있습니다.

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-9bf7c31374ac3f0ff189e8e464eb2d92e720b3b4%2Fsc-ha-before-register.png?alt=media)

### 2단계: 브릿지 스마트 컨트랙트 등록 및 구독 <a href="#step-2-registering-and-subscribing-the-bridge-contract" id="step-2-registering-and-subscribing-the-bridge-contract"></a>

위의 그림과 같이 브릿지 컨트랙트에는 EN-01과 SCN-L2-01의 브릿지만 등록되어 있습니다.

SCN-L2-02의 kscn 콘솔에 접속하여 브릿지 등록, 구독 및 토큰 등록을 위한 명령어를 실행합니다. The bridge and token contract were created while deploying the bridge contract with EN-01 and SCN-L2-01 in step 2 of [Cross-Chain Value Transfer](/content/installation-guide/deployment/service-chain/getting-started/value-transfer).

```
$ kscn attach --datadir ~/data
> subbridge.registerBridge("0xCHILD_BRIDGE_ADDR", "0xPARENT_BRIDGE_ADDR")
null
> subbridge.subscribeBridge("0xCHILD_BRIDGE_ADDR", "0xPARENT_BRIDGE_ADDR")
null
> subbridge.registerToken("0xCHILD_BRIDGE_ADDR", "0xPARENT_BRIDGE_ADDR", "0xCHILD_TOKEN_ADDR", "0XPARENT_TOKEN_ADDR")
null
```

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-d30969f5fffbe3104da072a2c373cd63e93c672f%2Fsc-ha-before-register2.png?alt=media)

추가된 브릿지에 대한 정보가 브릿지 컨트랙트에 반영되어야 합니다. [service-chain-value-transfer-example](https://github.com/klaytn/servicechain-value-transfer-examples)의 `erc20/erc20-addOperator4HA.js` 파일에 추가된 브릿지의 자식 및 부모 오퍼레이터 정보로 변경하고 `node erc20-addOperator4HA.js`를 실행합니다.

```
// register operator
await conf.child.newInstanceBridge.methods.registerOperator("0xCHILD_BRIDGE_ADDR").send({ from: conf.child.sender, gas: 100000000, value: 0 });
await conf.parent.newInstanceBridge.methods.registerOperator("0xPARENT_BRIDGE_ADDR").send({ from: conf.parent.sender, gas: 100000000, value: 0 });
```

브리지가 여러 개인 경우 임계값을 설정하여 더욱 안전하게 토큰 전송을 할 수 있습니다. 임계값 이상의 운영자들이 토큰 전송을 요청하는 경우에만 토큰 전송이 가능해 집니다. 예를 들어 현재 예제와 같이 브릿지가 2개 있고 임계값이 2로 설정되어 있으면, 두 브릿지의 오퍼레이터들이 모두 정상적으로 토큰 전송을 요청해야만 토큰 전송이 가능합니다. 만약 하나의 브릿지가 공격을 받아서 비정상적인 요청을 보내는 경우에 토큰 전송이 실행되지 않습니다. 임계값은 기본값은 1입니다. 아래 코드의 주석을 제거하고 임계값을 설정하는 코드를 실행하면 브릿지 컨트랙트의 임계값을 변경할 수 있습니다. .

```
// // set threshold
// await conf.child.newInstanceBridge.methods.setOperatorThreshold(0, "your threshold number").send({ from: conf.child.sender, gas: 100000000, value: 0 });
// await conf.parent.newInstanceBridge.methods.setOperatorThreshold(0, "your threshold number").send({ from: conf.parent.sender, gas: 100000000, value: 0 });
```

아래 그림과 같이 브릿지 컨트랙트에 EN-02와 SCN-L2-02 사이의 브릿지가 등록되어 HA를 구성합니다.

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-e003f52b9365ca6cabffb7372b771d220b7c88ba%2Fsc-ha-after-register.png?alt=media)

HA를 위해 두 개 이상의 브릿지가 연결되면 동일한 블록에 대한 데이터 앵커링 트랜잭션이 두 번 이상 발생하고, 토큰 전송을 위한 트랜잭션도 여러 번 발생할 수 있습니다. 즉, HA 구성으로 인해 수수료가 더 발생할 수 있다는 점에 주의하셔야 합니다.


# Nested ServiceChain

이번 장에서는 이전에서 구축한 ServiceChain 네트워크의 하위 계층으로 새로운 ServiceChain 네트워크를 추가하여 ServiceChain 네트워크를 계층적 구조로 구축하는 방법을 설명합니다. 추가할 ServiceChain 네트워크는 4개의 SCN으로 구성됩니다. 이전 장에서 구축한 ServiceChain 네트워크를 L2로 정의하고, 새롭게 구축할 ServiceChain 네트워크를 L3로 정의합니다. L2와 L3 사이에 브릿지를 연결하여 계층 구조를 만들 것입니다. 이번 장에서 구성할 ServiceChain 네트워크의 전체 구조는 아래 그림과 같습니다.

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-dc50a1eab22fcaf40aedfc660b74471b95653545%2Fsc-nestedsc-arch.png?alt=media)

### Prerequisites <a href="#prerequisites" id="prerequisites"></a>

* Assume that you have progressed to the ServiceChain configuration and Baobab EN described in [Nested ServiceChain](/content/installation-guide/deployment/service-chain/getting-started/nested-sc). 따라서 이전 섹션에서 설명한 내용은 간략하게 설명합니다.
* Assumptions and Limitations
  * 하나의 EN은 ServiceChain L2의 SCN 중 하나에 일대일로만 연결될 수 있습니다. 같은 방식으로, ServiceChain의 L2에 있는 하나의 SCN은 L3에 있는 SCN 중 하나에 일대일로 연결됩니다.
  * SCN 노드는 메인 브릿지와 서브 브릿지를 동시에 가질 수 있습니다. 단, 메인 브릿지와 서브 브릿지의 포트 번호는 다르게 설정해야 합니다. (예: 메인 브릿지 포트: 50505, 서브 브릿지 포트: 50506)
  * L2의 모든 SCN이 EN으로 브릿지가 될 필요가 없으며, 마찬가지로 L3의 SCN이 모두 L2로 연결될 필요도 없습니다. 그러나 고가용성을 위해 체인 간에 두 개 이상의 메인 브릿지 및 서브 브릿지 쌍이 있는 것이 좋습니다. 이 장에서는 L2와 L3 사이에 한 쌍만 연결을 설명하며, 만약 L2와 L3 사이의 고가용성을 보장하려면 Baobab과 L2 사이의 HA와 동일한 방식으로 구성하면 합니다.

### 1 단계 : L3를 위한 Homi 생성 및 업데이트 <a href="#step-1-create-and-update-homi" id="step-1-create-and-update-homi"></a>

L3 빌드를 위한 스크립트와 구성 파일을 생성하기 위해, ServiceChain L2를 구성할 때와 마찬가지로 homi 명령을 실행합니다. 모든 Linux/Mac PC에서 `homi`를 실행할 수 있습니다. 이전 예에서 Baobab의 `chainID`는 `1001`, L2의 `chainID`는 `1002`로 설정하였으므로 편의상 L3의 `chainID`를 `1003`으로 설정합니다. 실제 블록체인 서비스를 운용할 때는 다른 ServiceChains 체인 또는 EVM 체인과의 `chainID` 충돌을 방지하기 위해서 <https://chainlist.defillama.com/에> 새로운 `chainID` 값을 등록하신 후에 운용하시기를 권고합니다.

```console
$ ./homi setup --gen-type local --cn-num 4 --test-num 1 --servicechain --chainID 1003 --p2p-port 22323 -o homi-output
Created :  homi-output/keys/passwd1
Created :  homi-output/keys/passwd2
Created :  homi-output/keys/passwd3
Created :  homi-output/keys/passwd4
Created :  homi-output/scripts/genesis.json
Created :  homi-output/keys/nodekey1
Created :  homi-output/keys/validator1
Created :  homi-output/keys/nodekey2
Created :  homi-output/keys/validator2
Created :  homi-output/keys/nodekey3
Created :  homi-output/keys/validator3
Created :  homi-output/keys/nodekey4
Created :  homi-output/keys/validator4
Created :  homi-output/scripts/static-nodes.json
Created :  homi-output/keys_test/testkey1
Created :  homi-output/keys_test/keystore1/0xdC7218621513f71d609653d22C39d79d558d9CDC
Created :  homi-output/Klaytn.json
Created :  homi-output/Klaytn_txpool.json
```

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-2f33af1e41808a0b88fef82e4afa791e0686868a%2Fsc-nestedsc-ip.png?alt=media)

`homi-output/scripts/static-nodes.json`에서 ServiceChain L3 노드의 IP 주소 및 포트 정보를 업데이트합니다.

```json
[
     "kni://358235ccbf97a1f...787f7@192.168.0.21:22323?discport=0&type=cn",
     "kni://14ac4e3d53de5c7...6c91d@192.168.0.22:22323?discport=0&type=cn",
     "kni://5f36a456d93da09...8e216@192.168.0.23:22323?discport=0&type=cn",
     "kni://d62fd0928b9b6e5...6badf@192.168.0.24:22323?discport=0&type=cn"
]
```

ServiceChain L3의 모든 노드(SCN-L3-01, SCN-L3-02, SCN-L3-03, SCN-L3-04)에 homi의 실행 결과물을 복사합니다.

```console
$ scp -r path/to/homi-output user@192.168.0.21:~/ 
$ scp -r path/to/homi-output user@192.168.0.22:~/ 
$ scp -r path/to/homi-output user@192.168.0.23:~/ 
$ scp -r path/to/homi-output user@192.168.0.24:~/ 
```

모든 노드들을 초기화 시킵니다.

```console
$ kscn --datadir ~/data init ~/homi-output/scripts/genesis.json
$ ls ~/data
keystore    klay        kscn
```

모든 노드들(SCN-L3-01, SCN-L3-02, SCN-L3-03 및 SCN-L3-04)에 `static-nodes.json`을 데이터 폴더 `~/data`에 복사하고 `nodekey`를 하나씩 복사합니다.

```console
$ cp   ~/homi-output/scripts/static-nodes.json   ~/data/
$ cp   ~/homi-output/keys/nodekey{1..4}   ~/data/klay/nodekey
```

### 2 단계 : L3의 SCN 설정 <a href="#step-2-scn-configuration" id="step-2-scn-configuration"></a>

ServiceChain L3의 모든 노드들의 `conf/kscnd.conf` 파일을 아래와 같이 편집합니다. `PORT`는 ServiceChain의 기본 포트인 22323을 사용합니다. `DATA_DIR` 은 `~/data`로 설정합니다.

```
...
PORT=22323
...
DATA_DIR=~/data
...
```

L3의 모든 노드에서 ServiceChain을 실행하고 정상적으로 동작하는지 확인합니다.

```console
$ kscnd start
Starting kscnd: OK
$ kscn attach --datadir ~/data
> klay.blockNumber
10
```

### 3 단계 : L2 메인 브릿지 설정 후 재시작 <a href="#step-3-restart-after-setting-l2-main-bridge" id="step-3-restart-after-setting-l2-main-bridge"></a>

ServiceChain L2에서 메인 브릿지 역할을 할 SCN-L2-03 노드의 콘솔에 접속합니다. (주의: L3가 아니라 L2임)

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-9821c8b7ef2153b5c3f8b47e330374874ea48e27%2Fsc-nestedsc-id.png?alt=media)

SCN-L2-03의 kscn 설정 파일 `conf/kscnd.conf`를 다음과 같이 편집합니다.

```console
SC_MAIN_BRIDGE=1
```

SCN-L2-03에서 kscnd를 다시 시작합니다.

```console
SCN-L2-03$ kscnd stop
SCN-L2-03$ kscnd start
```

### 4 단계 : 메인 브릿지 노드의 KNI 확인 <a href="#step-4-check-kni-of-main-bridge-node" id="step-4-check-kni-of-main-bridge-node"></a>

SCN-L2-03 노드의 KNI 정보를 확인합니다. 이 값은 ServiceChain L3에서 서브 브릿지를 설치할 SCN-L3-01 노드의 `main-bridges.json` 파일을 생성하는 데 사용됩니다.

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-50cf4638383f8b0fafe9ce45cafb19297a4a95eb%2Fsc-nestedsc-nodeinfo.png?alt=media)

```console
SCN-L2-03$ kscn   attach   --datadir   ~/data
> mainbridge.nodeInfo.kni
"kni://87989a5a5dcc165...85b16b@[::]:50505?discport=0"
```

### 5단계 : L3 서브브릿지 설정 <a href="#step-5-configure-l3-sub-bridge" id="step-5-configure-l3-sub-bridge"></a>

ServiceChain L3의 서브 브릿지가 있는 SCN-L3-01 노드에 접속합니다. (주의: L2 아님) `~/data` 폴더 아래에 `main-bridges.json`을 생성합니다. @ 뒤의 \[::]를 4단계에서 확인했던 노드의 IP 주소로 바꿉니다.

```console
SCN-L3-01$ echo '["kni://87989a5a5dcc165...85b16b@192.168.0.13:50505?discport=0"]' > ~/data/main-bridges.json
```

서브브리지가 있는 SCN-L3-01 노드의 구성 파일 `conf/kscnd.conf`를 아래와 같이 편집합니다. 브릿지 연결을 활성화하려면 `SC_SUB_BRIDGE`를 1로 설정하고 `SC_PARENT_CHAIN_ID`는 L2의 `chainID`인 1002로 설정합니다. 데이터 엥커링을 위해 `SC_ANCHORING`을 1로 설정하면 재시작하면서 데이터 앵커링이 동작합니다. SCN-L3-01 쉘에 접속하여 `subbridge.anchoring(true)` 명령으로 데이터 앵커링을 켜고, `subbridge.anchoring(false)` 명령으로 끌 수도 있습니다. `SC_ANCHORING_PERIOD`는 앵커링 트랜잭션이 상위 체인으로 전송되는 주기를 결정하는 매개변수입니다. 이번 예제에서는 10으로 지정하여 10블록마다 데이터 앵커링을 수행합니다. 기본값은 1입니다.

```console
SC_SUB_BRIDGE=1
…
SC_PARENT_CHAIN_ID=1002
…
SC_ANCHORING=1
SC_ANCHORING_PERIOD=10
```

설정이 완료된 이후에 SCN-L3-01 노드의 kscnd 을 재시작합니다.

```console
SCN-L3-01$ kscnd stop
Shutting down kscnd: Killed
SCN-L3-01$ kscnd start
Starting kscnd: OK
```

`subbridge.peers.length`를 조회하여 SCN-L3-01이 SCN-L2-03에 연결되었는지 확인하고, `subbridge.latestAnchoredBlockNumber`를 죄회하여 가장 최근에 앵커링된 블록 번호로 앵커링이 진행 중인지 확인합니다.

```console
SCN-L3-01$ kscn attach --datadir ~/data
> subbridge.peers.length
1
> subbridge.latestAnchoredBlockNumber
5010
```


# Value Transfer between Sibling ServiceChains

이번 장에서는 서비스체인 네트워크 사이에 토큰 전송이 가능하도록 구성하는 방법을 설명합니다. 서비스체인에서 제공하는 주요 기능인 데이터 앵커링 및 토큰 전송은 서로 독립적으로 사용할 수 있습니다. 즉, 두 가지 기능을 모두 사용하지 않고, 데이터 앵커링만 사용하거나 토큰 전송만 사용할 수 있습니다.

아래 그림과 같이 Baobab에 연결된 두 개의 서비스체인(chainID 1002, 1004)이 있는 경우 각 서비스체인은 Baobab으로 데이터 앵커링을 수행하므로 두 서비스체인 간에 데이터 앵커링이 꼭 필요한 상황이 아니라면, 토큰 전송만 사용할 수 있니다.

두 서비스체인 사이에 브릿지가 없을 때 토큰 전송을 하려면, 먼저 한 서비스체인(chainID 1002)에서 Baobab(chainID 1001)로 토큰을 전송한 다음 Baobab(chainID 1001)에서 다른 서비스체인(chainID 1004)으로 토큰을 다시 전송해야 합니다. 이는 서비스체인(chainID 1002)에서 다른 서비스체인(chainID 1004)으로 한 번에 직접 가치 전달을 제공하는 것보다 비효율적입니다. 따라서 서비스체인 사이에 브릿지를 만들어 다른 서비스체인으로 직접 토큰 전송한다면 Baobab을 거치는 방법보다 효율적인 토큰 전송이 가능해 집니다.

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-04a399b6dccf8cf0ec4d4dedcc87f34dcf876da5%2Fsc-vt-between-sibling-arch.png?alt=media)

### Prerequisites <a href="#prerequisites" id="prerequisites"></a>

* 두 개의 서비스체인을 구성하고 각 서비스체인은 Baobab EN에 연결되어 있다고 가정합니다. [Connecting to Baobab](/content/installation-guide/deployment/service-chain/getting-started/en-scn-connection)를 참조하세요.
* 또한 [Cross-Chain Value Transfer](/content/installation-guide/deployment/service-chain/getting-started/value-transfer)를 통해 토큰 전송을 성공적으로 실행한 것을 가정합니다.

아래 그림과 같이 Baobab에 연결된 서비스체인(chianID 1004)을 추가로 설치합니다.

각 네트워크의 노드에 메인 브릿지와 서브 브릿지를 설치합니다. 이번 예제에서는 SCN-L2-03 노드와 SCN-L2-07 노드에 각각 메인 브릿지와 서브 브릿지를 설치하려고 합니다.

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-fd20e067e457c6f996ec9336008a1e95b51fb730%2Fsc-vt-between-sibling-bridge.png?alt=media)

### 1단계 : SCN-L2-03 노드의 KNI 설치 <a href="#step-1-check-kni-of-scn-node" id="step-1-check-kni-of-scn-node"></a>

SCN-L2-07 노드에서 서브 브릿지를 설정하기 위해 필요한 정보인 SCN-L2-03의 KNI를 잘 기억해 둡니다. 이 정보 `main-bridges.json` 파일을 생성하는 다음 단계에서 사용됩니다.

```
SCN-L2-03$ kscn attach --datadir ~/data
> mainbridge.nodeInfo.kni
"kni://...39047242eb86278689...@[::]:50505?discport=0"
```

### 2단계 : main-bridges.json 생성 <a href="#step-2-create-main-bridges-json" id="step-2-create-main-bridges-json"></a>

SCN-L2-07 (주의: chianID 1004) 쉘에 접속하여 `~/data`에 `main-bridges.json` 파일을 만듭니다. `@` 문자 뒤에 있는 `[::]`에 SCN-L2-03 노드의 IP 주소를 적습니다.

```
$ echo '["kni://...39047242eb86278689...@192.168.0.3:50505?discport=0"]' > ~/data/main-bridges.json
```

### 3단계 : SCN 설정 후 재시작 <a href="#step-3-configure-scn-then-restart" id="step-3-configure-scn-then-restart"></a>

SCN-L2-07 노드의 셸에서 `kscn-XXXXX-amd64/conf/kscnd.conf`를 편집합니다. 두 서비스체인은 이미 Baobab EN에 각각 앵커링되어 있으므로 서비츠체인 사이에 데이터 앵커링은 필요하지 않다고 가정합니다. 그래서 `SC_ANCHORING`을 0으로 설정했습니다.

```
...
SC_SUB_BRIDGE=1
...
SC_PARENT_CHAIN_ID=1002
...
SC_ANCHORING=0
...
```

SCN-L2-07 노드의 kscnd를 재시작합니다.

```
SCN-L2-07$ kscnd stop
Shutting down kscnd: Killed
SCN-L2-07$ kscnd start
Starting kscnd: OK
```

`subbridge.peers.length`을 조회하여 SCN-L2-07과 SCN-L2-03이 연결되어 있는지 확인하십시오.

```
SCN-L2-07$ kscn attach --datadir ~/data
> subbridge.peers.length
1
```

In the case of value transfer, if the information corresponding to chainID 1002 is used as the mainbridge information and the information corresponding to chainID 1004 is set as a subbridge, value transfer is possible between siblings as in [Cross-Chain Value Transfer](/content/installation-guide/deployment/service-chain/getting-started/value-transfer).


# 참조 매뉴얼

## Intended Audience <a href="#intended-audience" id="intended-audience"></a>

* Companies that want to build blockchains for Metaverse, GameFi, and NFTs
* dApp developers who need high TPS, minimal transaction fees, and data privacy.
* Anyone who wants to build a local private network or a ledger database for testing.

## ServiceChain Overview <a href="#service-chain-overview" id="service-chain-overview"></a>

ServiceChain is an enterprise-level blockchain to meet companies' requirements such as value transfer, security, high performance, and customization. Klaytn ServiceChain provides the following features:

* Immediate finality
* Token transfer between Klaytn chains
* Data anchoring to the main chain for data integrity
* Multi-sig bridge contract to meet enterprise-level security requirements

![](https://4178890574-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LqJV-03ampuHElwofFa%2Fuploads%2Fgit-blob-74e7ca6ad090dc033d45271a81b3672450280543%2Fsc-overview.png?alt=media)

Read the [Klaytn Scaling Solution](/content/klaytn/scaling-solutions) for more details about the ServiceChain. And the following videos will help you understand Klaytn ServiceChain.

* [Horizontal Scaling through Service Chain in Klaytn | TXGX 2019](https://www.youtube.com/watch?v=8yQc5FQysJc)
* [High Availability Architecture of Klaytn Service Chain | TXGX 2019](https://www.youtube.com/watch?v=HcdhWtXPuR0)


# System Requirements

시스템 요구 사항은 필요한 성능에 따라 좌우됩니다. 상업적 용도로는 엔드포인트 노드 및 코어 셀의 권장 사양을 참조할 수 있습니다.

* [엔드포인트 노드 시스템 요구사항](/content/installation-guide/deployment/endpoint-node/system-requirements)
* [코어 셀 시스템 요구사항](/content/installation-guide/deployment/core-cell/system-requirements)


# Download

You can get packages for SCN, SPN, and SEN in the [download page](/content/installation-guide/deployment/download).




---

[Next Page](/llms-full.txt/1)

