스마트 컨트랙트 알아보기
이번에는 테조스의 스마트 컨트랙트에 대해 알아보겠습니다.
이더리움에서는 operation fee로 gas를 지불하는데, 테조스에서는 storage와 operation두 가지에 대해 fee를 지불합니다. Storage fee는 컨트랙트를 배포(deploy)하거나 생성시킬 때 컨트랙트가 사용하는 네트워크의 저장 공간 1 byte당 수수료를 지불하는 것이고, operation fee(gas fee)는 컨트랙트를 생성하는 비용입니다. 저장공간을 새로 사용할 때만 storage fee를 내고, 저장되어 있는 내용을 수정할 때에는 operation fee만 지불하게 됩니다.
이제 간단한 컨트랙트를 디플로이하고 사용해 보겠습니다.
컨트랙트를 디플로이하는 명령어는
tezos-client originate contract <manager name> for <account name> transferring <xtz quantity> from <account name> running <program> 입니다.
컨트랙트의 종류, 사용법에 따라서 추가로 더 많은 명령어가 필요할 수 있습니다.터미널에 Tezos-client man contract를 입력하면 명령어 목록과 설명을 볼 수 있습니다.
이 튜토리얼은 문자열을 저장하는 간단한 컨트랙트로 진행하겠습니다.
id.tz를 디플로이 해보겠습니다. id.tz 컨트랙트는 테조스를 설치하면 기본적으로 설치되는 간단한 컨트랙트들을 모아놓은 tezos/src/bin_client/test/contracts 디렉토리에 있습니다.
id.tz 컨트랙트의 매니저를 alice로 설정하고, 코인은 bob의 계좌에서 보내게 하고, 문자열 hello로 초기화 해보겠습니다. 컨트랙트에서 어떤 코드도 생성하지 않기 때문에 코인이 필요하지는 않지만 보내보겠습니다.
이번에도 burn-cap 문제가 발생합니다. 일단 --burn-cap 0.303으로 설정해주고, 자세한 설명은 밑에서 진행하겠습니다.
컨트랙트가 블록에 담기면 영수증을 출력합니다. 영수증을 통해 gas fee, storage fee에 대해 자세히 알아보겠습니다.
tz1WBQ…주소를 가진 bob이 오퍼레이션을 생성했고, 0.00144xtz가 수수료로 사용됐습니다. 오퍼레이션의 고유한 번호인 counter는 30623이고, 설정해주지 않은 gas limit과 storage limit은 자동으로 11362, 323byte로 설정되었습니다. Balance updates 에서 수수료가 베이커에게 전달되었다는 것을 확인할 수 있습니다.
새로운 컨트랙트를 생성한 오퍼레이션이기 때문에 Origination이라고 표시됩니다. bob이 alice에게 manager 지위를 부여했기 때문에 bob와 alice의 주소가from: tz1WBQ…, For: tz1g6T…으로 표시되고, 컨트랙트에 전송했던 1xtz가 credit으로 표시됩니다.
Script에서는 컨트랙트 코드를 볼 수 있습니다. id.tz의 코드가 표시되고, 컨트랙트의 주소를 알려줍니다.
Storage size와 Paid storage size diff는 컨트랙트가 네트워크에서 사용하는 저장공간과 관련이 있습니다. 위에서 설명했듯이 storage fee는 byte당 지불하는 수수료이기 때문에 단위가 bytes로 표시됩니다. Storage size는 현재 컨트랙트가 사용하고 있는 저장공간 크기이고, Paid storage size diff는 이 오퍼레이션이 생성되기전과 후의 사용하는 저장공간 크기의 차이입니다. 모든 컨트랙트는 41bytes를 사용하고, 초기값으로 ‘hello’ 5bytes를 사용했기 때문에 46bytes가 됩니다. 처음 컨트랙트를 디플로이할 때는 아무것도 사용하지 않다가 저장공간을 새로 사용하기 때문에 Storage size와 Paid storage size diff가 46bytes로 똑같은 값이 나온 것입니다.
Balance updates는 operation fee가 아닌, storage fee와 origination에 대한 수수료와 credit으로 사용한 코인에 관한 정보입니다. 2,3주차에 언급되었던 --burn-cap이 이 storage fee, origination과 관련이 있습니다.
이제 ‘hello’로 초기화했던 문자열을 ‘world’로 수정해보겠습니다. transfer에 대한 추가 명령어는 tezos-client man transfer로 볼 수 있습니다.
코인을 전송할 필요가 없기 때문에 id에게0xtz를 보내고, --arg명령어로 문자열을 ‘world’로 변경해보겠습니다.
이번에는 ‘hello’와 ‘world’의 길이가 같으므로 추가로 사용하는 저장공간이 없기 때문에 Paid storage size diff가 생략되었습니다. 이 영수증은 parameter가 “world”이고, 업데이트 된 storage가 “world”라고 알려줍니다. 하지만 문자열의 길이가 길어지면 추가로 수수료를 내야합니다.
이번에는 네트워크의 저장공간을 추가로 사용해보겠습니다. --burn-cap없이 문자열을 “world!”로 6bytes를 사용하면
예상대로 burn-cap문제가 발생합니다. burn-cap을 0.001로 설정해주겠습니다.
영수증의 일부만 살펴보면, Paid storage size diff가 1bytes로 표시되고, 추가공간에 대한 수수료로 0.001xtz를 지불한 것을 알 수 있습니다.
오퍼레이션을 생성할 때, 코인을 보내는 것이든 스마트 컨트랙트를 디플로이하는 것이든 그 오퍼레이션은 베이커에 의해 실행 및 검증을 거치고 블록에 담기게 됩니다. 이 때 베이커도 자원을 소모하므로, 당신도 오퍼레이션 생성에 대한 비용을 지불해야 합니다. 이 때 필요한 것이 gas limit과 storage limit입니다. Gas limit과 storage limit은 노드가 거래를 블록에 포함시키기 위해 지불할 수 있는 최대 금액을 나타내기 위한 것입니다. 지금까지는 오퍼레이션을 생성할 때 storage limit과 gas limit에 대한 명시없이 오퍼레이션을 생성했습니다. 물론 높은 수수료를 가지는 오퍼레이션이 블록에 포함될 가능성이 높지만, 베이커도 오퍼레이션 검증에 자원을 사용한다는 점에서 storage limit,과 gas limit도 중요한 고려요소입니다. 그렇기 때문에 블록에 포함되기 위해서는 gas를 최대한 낮출 필요가 있습니다. Gas limit이나 storage limit이 크면 블록에 포함되는 데 시간이 오래걸리게 됩니다. 그래서 테조스에서는 gas limit과 storage limit을 명시해서 오퍼레이션을 생성하는 것을 권장합니다.
Gas limit을 20000으로 설정해서 다시 오퍼레이션을 생성해보겠습니다.
Gas limit이 20000으로 설정되고, 수수료도 상승한 것을 볼 수 있습니다.
account 생성을 통한 spam 공격*이 발생한 이후로, ddos 공격을 막기위해 오퍼레이션 생성에 최소 수수료가 들게끔 업데이트 되었습니다. Gas 1과 storage 1byte당 가격이 정해져 있습니다.
*spam 공격: spamming은 원하지 않는 메시지, 원하지 않는 광고를 많은 수신자에게 보내는 것입니다. 트로이 목마, 바이러스, 웜, 스파이웨어 등을 전달하는 데 사용될 수 있어 심각한 보안 위협을 초래합니다. 공격자는 비용이 거의 필요하지 않지만, 방대한 양의 데이터를 저장해야 하는 서비스 공급자는 심각한 위협에 처하게 됩니다.
--fee <amount>로 설정하는 gas fee는 operation fee로 gas limit과 관련이 있습니다. 최소수수료 minfee는 100 + (gas limit * 0.1) + opbytes로 설정됩니다. 이 minfee를 넘기지 못한 오퍼레이션을 생성하려하면 에러메세지가 표시됩니다. opbytes는 다른 계좌나 컨트랙트로 코인을 전송할 때는 약 162bytes, origination 오퍼레이션일 때는 약 185bytes로 계산합니다. 2주차에서 나왔던 코인 전송 시 최소수수료 0.00127xtz는 100 + (10100 * 0.1) + 162 =1272mtez로 계산된 것입니다.
Storage fee는 네트워크의 저장공간과 관련이 있습니다. Storage fee를 지불하는 경우는
1.오퍼레이션이 Origination오퍼레이션이거나
2.네트워크에 아직 알려지지 않은 새로운 주소(inactive)로 코인을 전송하는 경우
두가지로 257bytes를 사용합니다. 이 두 경우는 네트워크의 저장공간을 새로 사용하는 것이기 때문에 수수료를 추가로 지불해야 합니다. 이것이 바로 --burn-cap 이고, 1byte당 0.001xtz로 기본 0.257xtz입니다.
2, 3주차에서 진행했던 alice계좌에서 bob계좌로 처음 코인보내기, alice_del 컨트랙트를 생성해서 코인 위임하기에서 burn-cap 문제가 발생한 것도 각각 2번, 1번 문제에 해당하는 경우였기 때문입니다. 그 때는 저장공간을 추가로 사용하지 않았기 때문에 기본 수수료 burn-cap 0.257xtz만 지불하면 문제가 해결됐었습니다. 위에서 디플로이한 컨트랙트에서 burn-cap이 0.303이었던 이유는 컨트랙트와 초기값이 추가로 사용한 46bytes가 추가되어 0.257xtz와 0.046xtz를 합쳐 0.303xtz가 됐기 때문입니다.
지금까지 테조스 스마트 컨트랙트와 수수료에 대해서 알아보았습니다. 다음주에는 테조스 컨트랙트언어인 리퀴디티(liquidity)에 대해 알아보겠습니다.
작성자: 김승태
개발팀: 김승태, 김예서, 김형준