체인의정석

상용 서비스에 들어가는 Smart Contract 테스트 코드 작성 팁 본문

블록체인/Ethers & web3

상용 서비스에 들어가는 Smart Contract 테스트 코드 작성 팁

체인의정석 2022. 5. 30. 14:38
728x90
반응형

1. solidity coverage를 사용하여 라인 커버리지를 100%까지 올려야 한다.

https://www.npmjs.com/package/solidity-coverage

 

solidity-coverage

[![Gitter chat](https://badges.gitter.im/sc-forks/solidity-coverage.svg)][18] ![npm (tag)](https://img.shields.io/npm/v/solidity-coverage/latest) [![CircleCI](https://circleci.com/gh/sc-forks/solidity-coverage.svg?style=svg)][20] [![codecov](https://codec.

www.npmjs.com

해당 모듈을 사용하는 것이 좋다. 모듈을 통해 가져온 것은 체크 되지 않지만 내가 변경한 소스들 또는 새로 작성한 소스들은 예외상황 , 조건문에서 라인이 들어가는 부분 모두를 테스트 하여 오류가 발생하지 않도록 해야 한다.

 

2. 이벤트 로그를 통해 Internal Transaction을 모두 체크해야한다.

여러개의 컨트렉트가 상호작용하는 경우 CA에서 다른 CA로 인터널 트랜잭션이 발생할 수 있다. 그러나 이에 대한 이벤트 로그를 체크하지 않으면 중간에 다른 곳에서 다른 이벤트가 발생하거나 잘못된 정보가 들어갔는데 테스트 코드를 패스할 수 있다. 또한 인터널 트랜잭션을 다룰때 순서대로 이벤트 로그를 찍지 않으면 이벤트 로그 에러가 나게된다. 따라서 호출되는 순서를 정확히 따라서 제대로 된 이벤트 로그가 찍히는 지 확인해야 한다.

 

3. 에러를 리턴해야하는 상황에서 에러를 정확히 리턴하는지 일일히 체크해야한다.

0.5 버전 이하의 소스코드를 참고하는 경우 조건문에 오류 메세지가 뜨지 않을 수 있다. 이 경우 모두 오류메세지를 넣어주어야 테스트 코드에서 디버깅이 가능하다. 또한 에러를 정확히 리턴하는지 체크를 해주어서 에러 상황이 발생할 시 오류메세지가 정확히 나오나 체크해 주어야한다. 이를 체크하지 않을 시 뒷부분에서 원인 불명의 에러가 나기도 한다. 그러나 이런 에러는 에러에 대한 명시를 제대로 체크하고 넘어갈 시 해결되게 된다.

 

4. 단위 테스트만 진행하려 해도 시나리오 테스트 또한 할 수 밖에 없다.

스마트컨트렉트의 경우 단위 테스트를 진행 할 때 뒤의 함수를 실행시키기 위해서는 배포하는 컨트렉트나 사전에 진행되어야 하는 함수가 많기 때문에 기본적으로 단위 테스트를 할 때 시나리오 테스트 또한 해야 한다.

 

따라서 테스트 코드에 대한 안내문을 잘 작성하여야 한다. 다양한 상황을 다룰 경우 describe와 it을 통하여 단계별로 상황을 잘 작성해야 한다.

 

5. 시나리오 테스트를 최대한 많이 지속적으로 해야한다.

컨트렉트의 함수가 하나하나는 잘 작동하더라도 예외 상황이 발생할 경우는 계속해서 나올 수 있다. 따라서 예측가능한 모든 경우의 수에 대해서는 지속적으로 테스트 구문을 추가하는 다양한 시나리오 테스트가 필요하다.

 

6. 생각치 못한 오류가 날 경우에는 컴퓨터를 껐다 키는것이 답일 수도 있다.

컴퓨터를 계속 켜두면서 테스트 코드를 돌리다보면 이전에 되었던 것이 오류가 나는 경우도 있다. 하지만 컴퓨터를 껐다 키거나 환경을 다시 해보니 오류가 해결되는 경우도 있었다. 이전에 오류가 없었는데 갑자기 생긴 오류고 검토해도 답이 없다면 컴퓨터 또는 프로그램을 껐다 켜보고 다시 시도해 봐야한다.

 

7. 정말정말 모르겠는 오류가 생기면 최대한 자세히 로그를 찍고 나서 수치가 어떻게 변화하는지 차근차근 일일이 파악해본다.

hardhat 환경에서는 컨트렉트에 console.log를 찍어볼 수 있다. 또한 테스트 코드에서도 로그를 찍어볼 수 있다. 이를 이용하여 양쪽에 콜솔로그를 통해 오류가 발생하는 부분을 정확히 파악한 후 데이터를 넣어 본다. 만약 오류가 해결되었는지 확인하려면 다양한 상황에서 함수를 모두 실행해보고 모든 상황에서 제대로 된 값이 리턴되는지 확인해야 한다.

 

8. 오류가 나서 컨트렉트를 바꿔야 할 경우 마이그레이션 작업을 할 방안을 구상해 놔야 한다.

예상치 못한 오류가 발생했을 경우 컨트렉트에 대해 변경이 가능한 구조를 설계하거나, 새로운 컨트렉트를 배포 하여 서비스에 대한 이전이 가능하도록 처리해야 한다. 주로 애용하는 방법은 함수로 등록하고 수정하는 형태로 컨트렉트 끼리 연결되도록 modeifier로 등록시키고 이를 수정하는 함수를 만드는 방법과, 생성자에 마이그레이션 데이터를 직접 넣는 것을 같이 사용하는 방법이다. 

 

9. 관리자 권한, 비상상황에서 사용되는 함수 같은 경우 먼저 생각하여 물어보고 대응해야 한다.

긴급 상황에서 pause나 freeze등을 어느 레벨까지 작성해야 적용할지, 관리자는 몇명으로 두고 멀티시그는 적용할지 말지, 모든 컨트렉트에서 관리자를 둘지 등에 대한 관리 정보는 미리미리 알아 둔 후 테스트 시에 관리 함수에 대한 테스트 또한 진행해야 한다. 만약 멀티시그와 같은 추가 컨트렉트가 있을 시 이에 대한 테스트 코드는 파일을 따로 만들어서 역시 커버리지 100%로 올리도록 한다.

 

10. 다양한 툴을 활용한다.

만약 로컬에서 답이 안나올 경우 remix, tenderly 등을 통해서 다양한 값을 대입해보면서 테스트넷 환경에서 테스트를 진행한다. 또는 참고한 원본 소스의 이더스캔에 들어가서 함수의 작동을 분석해보고 그대로 적용시켜 본다. gas reporter등도 잘 활용하면 좋다.

 

11. Audit을 너무 의존하면 안된다.

오딧의 경우 함수의 작동까지 보장해주지 않는다. 단지 코드의 보안 결함을 잡아줄 뿐이다. 오딧을 진행한다고 테스트 코드를 가볍게 짜서는 안된다. 모든 행위는 직접 테스트 코드를 짜서 블록체인 위의 데이터를 변화시키고 읽어오고 이벤트로그를 인터널 트랜잭션 하나하나 가져와서 체크해야 한다. 물론 오딧을 받으면 도움을 받을 수는 있지만 오딧을 받았다고 해서 오딧업체가 문제 발생시 책임을 지는것도 아니며 보안 사항에 결함이 없어도 논리적인 결함이 있으면 서비스가 망가지거나 해킹당할 수 있다.

 

필자의 블록체인 강의

https://www.youtube.com/watch?v=ccefK05M0OI 

 

728x90
반응형
Comments