대납을 사용하여 컨트랙트 배포를 어떻게 하나요?

대납을 사용하여 컨트랙트를 배포하기 위해서는 ‘FEE_DELEGATED_SMART_CONTRACT_DEPLOY’ 타입이나 'FEE_DELEGATED_SMART_CONTRACT_DEPLOY_WITH_RATIO’타입의 트랜잭션을 전송하면 됩니다.

그럼 먼저 두 트랜잭션 타입의 차이점에 대해서 간단하게 설명드리겠습니다.

대납 트랜잭션

대납 트랜잭션이란, 수수료 대납자가 트랜잭션을 실행할 때에 필요한 수수료를 대신 지불하는 트랜잭션입니다. Klaytn은 수수료의 100%를 모두 대납자가 부담하는 경우와 서비스 사용자(트랜잭션을 생성하는 사용자)와 서비스 제공자가 부담하는 수수료의 비율을 정할 수 있는 경우 모두 지원합니다.

수수료의 100%를 모두 수수료 대납자가 부담하는 트랜잭션을 사용하는 경우 caver-js에서 ‘FEE_DELEGATED_*’ 타입의 트랜잭션을 사용하면 됩니다.

만약 수수료를 지불하는 비율을 정하고자 한다면 'FEE_DELEGATED_*_WITH_RATIO’라는 트랜잭션 타입을 사용하면 됩니다.

참고로, 수수료 대납 트랜잭션은 트랜잭션을 실제로 발생시키는 서비스 사용자와 수수료를 대납하는 서비스 제공자의 서명이 모두 필요합니다.

수수료 대납하여 트랜잭션 배포하기

그럼 실제로 caver-js를 통해 대납으로 스마트 컨트랙트를 배포하는 방법에 대해서 알아볼까요?

아래부터는 개발 환경과 테스트에 사용할 계정이 모두 갖추어져 있다는 것을 전제로 설명됩니다. 만약 처음 시작한다면 Klaytn Docs를 참고하여 개발 환경을 세팅하고 충분한 테스트넷 KLAY를 소유하고 있는 계정을 준비해 주세요.

테스트 계정 추가하기

테스트넷 KLAY를 충분히 가지고 있는 계정이 준비되었다면, 이를 caver-js의 in-memory wallet에 아래와 같이 추가합니다.

const caver = new Caver('http://13.125.198.123:8551/')

const address = '0x474d331644171af43e50b5414a4b47c8abfc6f32'
const key = '55288a6f1b2390d7c592d22b7aa7c0a9f14f895aa4cf39b3da62b5502a2f6b16'
// create Account instance
const account = caver.klay.accounts.createWithAccountKey(address, key)
// Add to in-memory wallet
caver.klay.accounts.wallet.add(account)

const feePayerAddress = '0xbe3590e4060259b9b45c8a9248c2c928a3694a26'
const feePayerKey = 'f5a23d229e11753cea04500fa916e14ebf1a8166cfeca69988e54f682578e674'
const feePayerAccount = caver.klay.accounts.createWithAccountKey(feePayerAddress, feePayerKey)
caver.klay.accounts.wallet.add(feePayerAccount)

in-memory wallet에 계정을 추가한 이후, caver.klay.accounts에 트랜잭션 서명 요청을 보내면 내부에 저장된 계정의 키로 서명하여 리턴합니다.

대납 트랜잭션 생성하기

여기서는 대납으로 스마트 컨트랙트를 배포하기 위하여 ‘FEE_DELEGATED_SMART_CONTRACT_WITH_RATIO’ 타입의 트랜잭션을 사용합니다.

const txObject = {
    type: 'FEE_DELEGATED_SMART_CONTRACT_DEPLOY_WITH_RATIO',
    from: account.address,
    data: '0x{byte code}',
    value: 0,
    gas: 3500000,
    feeRatio: 80,
}

위 예제의 data에는 배포하고자 하는 컨트랙트의 바이트 코드(생성자의 인자를 포함한 값)를 입력해 주세요. 바이트 코드를 구하는 방법에 대해서는 encodeContractDeploy를 참고하세요.

그리고 feeRatio에 지정된 80의 의미는 수수료 대납자가 80%의 수수료를 대납하며, 서비스 사용자(트랜잭션을 발생시킨 사용자)가 20%의 수수료를 지불한다는 의미입니다.

서명하기

위에서 생성한 트랜잭션을 서명해 볼까요? 아까 위에서 말했듯이, 트랜잭션을 생성한 서비스 사용자와 수수료를 대납할 서비스 제공자 모두의 서명이 필요합니다.

그럼 먼저 서비스 사용자의 서명을 해봅시다.

const senderSigned = await caver.klay.accounts.signTransaction(txObject)

위의 코드는 in-memory wallet 내부에서 from 주소에 해당하는 계정의 키로 트랜잭션에 서명한 뒤 결과를 리턴합니다. 해당 리턴 오브젝트 내부에는 ‘rawTransaction’ 필드에 RLP-encoded signed transaction이 함께 리턴됩니다. 수수료 대납자는 rawTransaction을 통하여 서명을 할 수 있습니다. 그럼 수수료 대납자도 이제 서명을 해볼까요?

const feePayerSigned = await caver.klay.accounts.feePayerSignTransaction(senderSigned.rawTransaction, feePayerAccount.address)

위에 예제에 보면 senderSigned.rawTransaction을 파라미터로 첫 번째 파라미터로 전송합니다. 이 값에는 트랜잭션의 정보와 서비스 사용자(트랜잭션을 발생시킨 사용자)의 서명이 모두 포함되어 있습니다. 그리고 두 번째 파라미터로는 수수료 대납자의 주소를 전달합니다. feePayerSignTransation은 전달 받은 트랜잭션에 수수료 대납자로써 서명한 후 결과값을 리턴합니다. 이전과 동일하게 ‘rawTransaction’ 필드에는 RLP-encoded signed transaction이 함께 리턴됩니다. 이 값에는 서비스 사용자와 서비스 제공자의 서명이 모두 포함되어 있습니다.

트랜잭션 전송하기

트랜잭션에 서명까지 완료했다면, 이제 네트워크에 전송하여 실제로 스마트 컨트랙트를 배포하는 작업만 남아있습니다.

const receipt = await caver.klay.sendSignedTransaction(feePayerSigned.rawTransaction)
console.log(receipt)

RLP-encoded signed transaction을 파라미터로 caver.klay.sendSignedTransaction을 호출하면 네트워크로 트랜잭션을 전송하여 실제로 스마트 컨트랙트를 배포할 수 있습니다.

결론

caver-js를 통하여 대납을 하는 방법을 간단합니다. ‘FEE_DELEGATED_*’ 타입의 트랜잭션을 생성하고, 트랜잭션을 발생시킨 서비스 사용자와 수수료를 대납하는 서비스 제공자 모두 트랜잭션에 서명한 뒤, 네트워크로 전송하면 됩니다.

이해가 안되는 부분이나 추가적인 궁금증이 있는 경우에는 편하게 댓글을 남겨주세요 ! :hugs:

1개의 좋아요

KAS의 Global Fee Payer 기능을 사용하면 KAS 계정에서 후불로 과금하는 것으로 알고 있습니다.

Caver-js를 이용하여 수수료 대납을 KAS의 Global Fee Payer로 할 수 있을까요?

Caver-js 와 Caver-js-ext-kas 를 같이 써야 할 것 같은데 아직 너무 막연해서 문의 드립니다.

안녕하세요.
각 트랜잭션마다 KAS의 global fee payer를 사용할 수 있는 기능이 따로 제공되고 있습니다.
Tutorial의 트랜잭션 전송 파트에서 KAS에서 트랜잭션 전송 수수료를 부담하기쪽의 js예제탭을 보시면 됩니다.
문서 참고 부탁드립니다.