정밀도 손실 및 반올림 취약점
스마트 컨트랙트가 자금을 잃기 위해 반드시 액세스 제어(access control) 버그가 필요한 것은 아닙니다.
때로는 단순한 나눗셈 속에 취약점이 숨어 있습니다.
금융 스마트 컨트랙트는 정수 산술(integer arithmetic)을 사용합니다. 소수점 이하는 버려집니다. 이러한 반올림 방향은 가치를 누가 가져가는지를 결정합니다. 단 1단위의 오차라도 수천 건의 트랜잭션을 통해 반복될 수 있습니다.
금융 프로토콜에서 반올림은 가치 이전 정책(value-transfer policy)입니다.
모든 나눗셈은 다음 세 가지 질문에 답할 수 있어야 합니다:
- 계산이 어느 방향으로 반올림되는가?
- 그 방향으로 인해 어느 측이 이득을 보는가?
- 공격자가 그 이득을 반복하거나 증폭시킬 수 있는가?
흔히 발생하는 수학적 오류는 다음과 같습니다:
너무 이른 시점의 나눗셈 곱하기 전에 나누기를 하면 정밀도를 잃게 됩니다. 예시: (amount / 1e18) * rate. 중간 단계의 나눗셈이 곱셈이 수행되기 전에 데이터를 버립니다. 규칙: 항상 나누기 전에 곱셈을 먼저 수행하십시오.
중간 단계의 오버플로우 최종 결과값이 uint256 범위 내에 있더라도, 먼저 곱셈을 수행하면 오버플로우가 발생할 수 있습니다. OpenZeppelin Math와 같은 라이브러리를 사용하여 정밀도를 유지한 채 곱셈과 나눗셈을 한 단계로 수행하십시오.
잘못된 방향의 반올림 반올림은 권장 사항이 아니라 보안 규칙입니다. 보수적인 프로토콜은 다음 원칙을 따릅니다:
- 부채는 올림(upward) 처리합니다.
- 지불해야 할 금액은 올림 처리합니다.
- 담보 가치는 내림(downward) 처리합니다.
- 사용자에게 지급되는 자산은 내림 처리합니다.
- 사용자에게 부과되는 지분(shares)은 올림 처리합니다.
정확한 결과를 얻을 수 없을 때는 가치를 추출하려는 측에 불리하도록 반올림하십시오.
- 인플레이션 공격 유동성이 낮은 금고(vault)에서 공격자는 기부(donation)를 이용해 환율을 조작할 수 있습니다. 공격자는 지분(share) 수를 늘리지 않고 총 자산 수만 늘리기 위해 자산을 기부합니다. 이로 인해 새로운 예치금이 0 지분으로 내림 처리됩니다. 완화 방법: 가상 자산(virtual assets)이나 가상 지분(virtual