일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 컨트렉트 동일한 함수이름 호출
- 러스트기초
- nestjs 튜토리얼
- ethers typescript
- nest.js설명
- 스마트컨트렉트 예약어 함수이름 중복
- ethers websocket
- 스마트컨트렉트 함수이름 중복 호출
- Vue.js
- Vue
- ethers v6
- git rebase
- 스마트 컨트렉트 함수이름 중복
- 스마트컨트렉트테스트
- 머신러닝기초
- multicall
- 컨트렉트 배포 자동화
- 깃허브명령어
- vue기초
- ethers type
- ethers
- 체인의정석
- SBT표준
- 프록시배포구조
- 스마트컨트렉트프록시
- ambiguous function description
- rust 기초
- 러스트 기초 학습
- chainlink 설명
- 러스트 기초
- Today
- Total
체인의정석
프로젝트 후기] GINI 프로젝트 - Klaytn, Ethereum 본문
해당 스마트컨트렉트에 대한 설명은 gini.fun에서 확인할 수 있다.
핵심 로직인 로또, 기부와 토큰은 스마트컨트렉트로 구현되었으며, 특히 당첨금을 배분할 때 추천인 시스템이 들어가서 레벨별 지급되는 당첨금이 다르게 나오는 식으로 구성되었다.
여태까지 해봤던 스마트컨트렉트 중 가장 복잡하였으며, 테스트 시나리오 또한 매우 다양하고 길었다.
로또 스마트컨트렉트
먼저 랜덤번호를 생성하고 당첨자를 계산하여 분배해주고, 당첨자가 나올 때
1. 랜덤번호 생성
2. XOR 연산으로 3개 블록의 해시값을 합친다.
3. shift 계산 후에 25를 나눈 후 1을 더한다.
4. 티켓의 표시는 2의 지수제곱 자리수에 1을 더하는 식으로 한다.
기부 - 기부는 로또 스마트컨트렉트와 연결하여 처음에 구매를 할때 후보를 지정하면 당첨자가 나올 시 해당 당첨자의 당첨금중 지정한 수량 만큼이 기부금으로 들어가서 기부단체 주소로 입금이 되는 식이다.
전체적인 구성은 라운드 별로 진행이 되었으며, 스마트 컨트렉트에서도 각 라운드 별로 데이터를 초기화 할 수 있도록 분리하였다.
특히 가장 문제가 되는 부분은 1,2,3등 당첨자와 당첨자 주소를 알고 어디로 투표했는지 까지 저장해야 하는 부분이였는데 여기서 가스 관련 이슈가 발생하여서 결국 이더리움으로 만들다가 도중에 카카오의 클레이튼으로 옮겼다.
덕분에 다른곳에서 경험해보기 어려운 메인넷을 도중에 바꾸는 작업을 진행하였으며, 카카오의 클레이튼 메인넷을 집중적으로 연구하는 기간도 가질 수 있었다.
이런식으로 UI에서는 기부율이나 어디에 기부할지 번호를 어떤걸로 할지에 대한 정보를 저장시킨다. 매번 트랜잭션을 보내면 가스비가 너무 많이 나오기 때문에 실제로는 트랜잭션을 묶어서 처리하는 식으로 구현하였다.
UX로 구분한 단계를 스마트컨트렉트 상에서 가능한 세세하게 함수로 쪼개어 구조체를 하나 만들어 둔 후 조건문을 걸어서 앞의 함수가 실행 될 때 변수를 변화시키고 그 변수가 변화되었는지를 다음 함수의 조건으로 걸어 무조건 순서대로만 실행할 수 있게 만들었다. 단계를 최대한 세세하게 쪼갠 이유는 각각 단계별로 이벤트 로그를 남겨서 나중에 데이터를 모니터링 할 수 있는 시간도 더 세분화 시키는 것도 있었으며, 블록의 size limit도 있어서 만약 대량의 유저가 로또에 참여했을 경우도 대비하여 몇명의 유저까지 감당이 가능한지 봤었어야 했기 때문이다.
특히 클레이튼의 경우 scope가 당시에 이벤트 값도 보여주지 않고 제대로 되어 있지 않아서 이를 따로 모아서 DB에 저장하고 bytecode를 직접 비교해가며 제대로 된 정보가 들어갔는지 확인하기도 했었다.
시간이 의외로 많이 들었던 부분은 문제 상황에 대한 마이그레이션 테스트였다. 실제 상황에서 문제가 발생할 경우 스마트컨트렉트는 변동이 불가능하기 때문에 발생했던 트랜잭션에 대한 input값을 해당 라운드가 끝날때 까지 모두 기록해 두고 있다가 문제가 발생하면 스마트컨트렉트의 일정 부분만을 변경하여 다시 배포하면 해당 라운드의 문제가 생기기 이전 상태로 돌아와야 했다.
이를 해결하기 위해서 문제 발생시에는 기부를 투표한 경우 constructor를 활용하여 internal로 된 함수를 호출해주고 시작하여 처음 투표를 해주고 시작을 하는 방식을 선택하였다. 사전에 문제가 될 데이터들은 모두 상황에 맞추어 초기화 시켜준 후 문제가 발생하기 까지 진행된 데이터를 DB에서 꺼내와 다시 트랜잭션으로 보내는 식으로 하여 만약 문제가 발생하여도 즉시 재배포를 하여 스마트컨트렉트가 계속해서 돌아갈 수 있도록 하였다.
여러 문제상황에 대한 테스트와 이를 해결하기 위한 회의를 진행하면서 다양한 측면에서의 경험을 하였으며, 그동안 간단한 스마트컨트렉트만 짜다가 이렇게 단계를 나누고 대량유저를 고려하여 생각하다보니 스마트컨트렉트라는게 얼마나 깊게 생각을 해야하는 언어인지 깨닫게 되는 프로젝트였다. 이후로 더이상 스마트컨트렉트를 보고 쉬운언어라고 생각하지 않는다. 코드는 짧지만 그 짧은 코드에 대한 무게는 상상 이상으로 무거웠다. 이렇게 코드는 짧아도 엄청난 사고를 통해서 만들어지는 코드라는게 또 스마트컨트렉트의 묘미 인것 같다.
테스트용 깃허브 주소 : github.com/hyunkicho/ETH-KLAYTN-testing
Contact : timehacker95@gmail.com
유튜브 : www.youtube.com/channel/UCHsRy47P2KlE749oAAjb0Yg?view_as=subscriber
'블록체인 > 퍼블릭 블록체인' 카테고리의 다른 글
Solidity 코드 로컬환경 & Remix에서 배포하기 (0) | 2021.01.28 |
---|---|
erc20파일 노드에서 더 편하게 관리하는 법 npm @openaeppelin/contracts (0) | 2021.01.28 |
Truffle 배포 후 web3에 abi인식 시키기 (0) | 2021.01.26 |
라인해커톤 참여기2) 서버와 DB 연동하기 (0) | 2020.12.18 |
라인 블록체인 해커톤 01 - 데이터베이스 구축 및 배포 (0) | 2020.12.17 |