Kleva Protocol Incident: Root Cause Analysis
안녕하세요, 수호아이오 오딧 팀입니다.
Kleva Protocol Incident: Root Cause Analysis

안녕하세요, 수호아이오 오딧 팀입니다.
수호아이오 오딧 팀은 건전한 커뮤니티 조성을 위하여 정확한 사고 원인 규명 및 해당 사건과 수호아이오 오딧팀의 관계성을 밝히는 것을 목적으로 본 문서를 작성하였음을 밝힙니다.
사고 개요
이번 2022년 1월 27일 19:28 KST에 Kleva Protocol의 코드 업데이트가 있었고, 그 과정에서 Vault(Lend, Stake, Farm 기능을 관리하는 핵심 컨트랙트)의 이자 계산 로직에 잘못된 multiplier가 곱해져 비정상적으로 큰 이자가 지급되는 사고가 일어났습니다. 그 결과, 총 52,389,039 KUSDT 의 피해가 발생하였습니다.
KLEVA 팀은 수호아이오 오딧 팀의 검토 내용에 따라 수정 패치를 진행중이며, 99.4% 이상의 자산이 회수 확정되었습니다. KLEVA 팀은 본 이슈로 손해를 본 모든 참여자들의 리스트는 확보 완료되었으며, 해당 참여자들의 손실은 전액 보전될 예정임을 밝혔습니다.
- Kleva Protocol이란
Kleva Protocol은 레버리지 이자 농사 서비스를 전문적으로 제공하는 Klaytn의 DeFi 프로토콜입니다. Kleva Protocol에 관한 자세한 내용은 KLEVA 공식 문서를 참조하시기 바랍니다.
사고 원인 규명
2022년 1월 27일 19:28 KST에 KLEVA 팀이 ibUSDT Contract의 업데이트를 진행합니다. 업데이트 내용은 다음과 같습니다: 초당 이자율 계산에 사용되는 단위 변수(DENOM)를 10의 18승에서 10의 6승으로 바꾸는 패치였습니다.
[embed]패치 전 ibKUSDT Vault Contract Code의 일부
[embed]패치 후 ibKUSDT Vault Contract Code의 일부
이 패치는 ibKUSDT Vault의 이자 지급 테스트 과정 중에서 이자 계산 함수인 calcPendingInterest가 계속 0을 반환하여 투자자들에게 이자가 지급되지 않는 오류를 수정하기 위해서 진행된 패치였습니다.
이자는 아래의 코드와 같이 초당 이자율인 ratePerSec과 총 토큰 대출 규모 값인 totalDebtAmount, 그리고 마지막 이자 계산으로부터 초과한 시간인 timePast의 곱을 단위 변수로 나눈 값이 됩니다.
즉, 마지막 이자 지급으로 부터 지난 시간만큼 초당 이자율을 총 대출 규모에 대해서 계산해서 정확한 이자 지급양을 계산하는 식인 것입니다. 테스트 과정에서 대출이 발생 했음에도 이자가 계속 0으로 나와 KLEVA 팀은 단위 변수인 DENOM이 총 토큰 대출 규모 값인 totalDebtAmount의 자릿수인 10의 6승 (KUSDT의 토큰 자릿수)에 연관되어 있다고 판단하고 위와 같은 패치를 진행하게 됩니다.
[embed]ibKUSDT Vault Contract의 이자 계산 함수
하지만 사실 단위 변수는 초당 이자율인 ratePerSec에 연관되어 있고, ratePerSec은 10의 18승을 기준으로 계산하는 것이 맞기 때문에, DENOM을 수정할 필요는 없었습니다.
실제로 calcPendingInterest의 값이 계속 0이 나온 이유는 QA 과정에서 발생한 대출금의 규모가 전체 예치 자산에 비해 매우 작았고, ibKUSDT Vault의 입출금이 굉장히 잦았기 때문입니다. ibKUSDT Vault의 이자 계산은 매 입/출금마다 호출됩니다.
[embed]ratePerSec의 계산 코드 일부
초당 이자율인 ratePerSec은 다음과 같이 계산되는데, 간단히 설명하자면, 전체 예치금 중 대출액이 차지하는 비율이 높을 수록 (가동율이 높을 수록) 높은 이자를 계산합니다. 그리고 그 이자를 초당으로 분할하여 값을 계산해 줍니다.
테스트로 넣어뒀던 대출(371 KUSDT)은 전체 예치금의 1%도 되지 않기 때문에, 10의 -14승 만큼 작은 초당 이자율을 계산하게 됩니다. Solidity는 소숫점 계산을 하지 못하기 때문에 단위 변수를 곱하면 10의 4승 정도 되는 값으로 나오게 됩니다.
다시 calcPendingInterest로 돌아오면, 10의 4승정도 되는 ratePerSec과 10의 9승 정도 되는 totalDebtAmount, 그리고 timePast를 곱한 값이 DENOM인 10의 18승보다는 커야 0보다 큰 값이 나오고, 그러기 위해서는 timePast는 최소 10의 5승, 최소 반나절 간격으로 호출되어야 1보다 큰 값이 나오게 되는 것입니다. 하지만 실제로 ibKUSDT Vault는 1분에 한두번 꼴로 입출금이 이루어지고 있었기 때문에, 이자 계산은 계속 0이 나왔던 것입니다.
결과적으로 이 패치로 인하여 의도된 이자보다 10의 12승 배 더 많은 양이 이자로 계산되어 출금 양에 영향을 주게 되었습니다.
이에, 2022년 1월 27일 19:32 KST에 KLEVA 팀이 새로운 코드 업데이트를 통하여 모든 출금을 차단한 22분 사이에 지갑주소 0x02c6…와 0x6ffa… 로 약 52,389,313 KUSDT가 과지급되었습니다.
현 커뮤니티 인식과 실 사고원인의 차이점
아래 내용에서 ‘커뮤니티의 인식’은 현재 발행된 Post-mortem analysis 를참고한 것이며, 실제 시각과 다를 수 있음을 밝힙니다.
현 사고의 초기 원인이 커뮤니티 내에서 decimal 설정의 문제로 인해 이자가 계산되지 않은 것으로 인식되고 있는 것과 달리, 실제로는 애초에 e18 decimal을 기준으로 이자 계산 주기와 최소 이자 크기를 설계한 것이기 때문에 초기에 이자가 지급되지 않는 버그가 발생하였던 것입니다.
더군다나 블록타임이 1초로 짧고 가스비가 거의 없어 transaction 생성이 잦은 체인 특성상 이자지급 주기가 예상보다도 훨씬 짧아지게 되어 충분한 이자가 쌓일 시간이 없었습니다.
현 사고와 수호아이오 오딧팀과의 관계성
우선, 수호아이오의 오딧 팀은 공정한 보안 감사를 위하여 Kleva 개발팀과는 철저히 분리된 외부 업체의 입장으로 오딧에 참여하였음을 밝힙니다.
이에 다른 외부 오딧 업체들과 마찬가지로 오류가 발생한 업데이트 코드에 대해서는 감사를 요청받은 바 없으며, 따라서 해당 오류 코드에 대한 보안 감사는 수호아이오 오딧 팀에서 진행하지 않았습니다.
그러나 ‘수호아이오’가 이번 Kleva Protocol 사업과 특수 관계에 있다는 점을 감안한다면, 외부 오딧 업체들과는 질적으로 다른 깊이 있는 접근법을 고안하고 코드 업데이트에 대한 선제적 오딧을 제안할 필요가 있었을 것입니다.
그렇기에 수호아이오 오딧 팀은 금번 사고에 대한 책임을 통감하며, 재발 방지를 위해 Kleva 개발팀과 긴밀히 협업하여 향후에 있을 크고 작은 모든 업데이트 건들에 대해 선제적인 오딧을 진행할 것을 약속드립니다.
결론
수호아이오 오딧 팀은 이번 사고로 인해 불명확한 오딧 Scope의 명시와 특수관계에 있는 클라이언트와의 세밀하지 못한 소통이 결과적으로 서비스 신뢰도에 영향을 미침을 경험하였습니다. 보안의 영역에서 서비스를 제공하는 팀이니만큼 더 신중하게 접근해야 했음을 절감합니다.
현재, 수호아이오 오딧 팀이 보안 감사를 마친 코드 Status에서 보안 사고가 발생한 적은 없습니다. 그러나, 이번 일을 통하여 기술적 역량만큼이나 절차적인 부분에 있어서의 미흡함도 서비스의 결함으로 이어질 수 있음을 깨닫고, 해당 절차적 부분에서의 보완에 만전을 기할 것을 약속드립니다.
마지막으로, 관련하여 수호아이오 오딧팀은 Kleva 개발팀의 보안 파트너로서 아낌없는 지원과 조언을 통해 해당 사고의 조속한 해결 및 서비스 정상화를 함께 꾀할 것임을 밝힙니다.
메타데이터
- post_id
- 80c20b8a2186
- slug
- kleva-protocol-incident-root-cause-analysis-80c20b8a2186
- url
- https://medium.com/soohoio/kleva-protocol-incident-root-cause-analysis-80c20b8a2186
- canonical_url
- https://medium.com/soohoio/kleva-protocol-incident-root-cause-analysis-80c20b8a2186
- author_url
- https://medium.com/@webmaster_20508
- status
- ok
- fetched_at
- 2026-07-27 13:01:19