outputAmt_
가 동일한지 확인하는 과정에서 좌측과 우측 모두 동일한 변수를 두고 비교를 하고 있다. 이 때 문제가 되는 점은 계산 순서가 명확하게 정의되지 않았다는 것이다. 어떤 것 부터 계산하느냐에 따라 결과가 달라질 수 있다.
Solidity docs에 따르면 모호하게 쓰인 표현의 계산 순서는 아직 정해지지 않았다. 즉 정확한 순서가 없기 때문에 나중에 solidity 버전이 올라가면서 순서가 정해진다면 해당 코드는 현재 버전과 다른 결과를 리턴할 수 있다. 따라서 현재보다 조금 더 명확한 순서로 작성되어야 한다. 더 간단한 예시는 다음과 같다.
function foo () public pure returns (uint) {
uint x = 5;
return x * x++; // Could be 25 or 30
}
컨트랙트에서 하드코딩은 지양해야 한다. 그것이 토큰의 스왑비율이라면 더욱 더 주의가 필요하다. 토큰의 가격은 항상 검증된 오라클을 사용하도록 하자.
0x 프로토콜에서 gasPrice
와 protocolFeeMultiplier
를 곱한 값을 수수료로 부과하고 있다. protocolFeeMultiplier
는 거버넌스에서 정하는 반면 gasPrice
는 사용자가 직접 입력할 수 있다. 이 때, 사용자가 입려하는 gasPrice
의 최소값을 확인하는 코드가 없다. 따라서 거버넌스에서 정한 protocolFeeMultiplier
가 높다고 하더라도 사용자는 0을 값으로 넘길 수 있으며, 정해진 수수료를 무시할 수 있다. 이를 방지하기 위해 gasPrice
의 최솟값을 정해두는 것이 바람직하다.
65번과 마찬가지로 파라미터 값을 변경할 때, 해당 값이 valid한 값인지 확인하는 과정이 있어야 한다. 그렇지 않으면 변경 전에 잘 작동하던 함수들이 변경 후 예상과 다르게 동작할 수 있기 때문이다.
Audit Findings 글에 더 많은 Audit 사례들이 있다. 하지만 막상 들어가보면 코드 없이 설명만 있는 사례들이 많아서 전체 코드를 보지 않는 한 이해하기 힘들었다. 실력을 쌓기 위해 과거 보고서를 읽는 것도 중요하지만 아래 사이클을 여러 번 돌려보는 것이 지금 내 수준에서 가장 많은 도움이 되는 방법이 아닐까 싶다.
아직 많이 부족하지만 이제 Code4rena에서 warden으로 활동해보면서 여러 프로젝트를 경험해보려 한다. 모르면 찾아보고 디스코드에서 질문도 해보면서 실력을 키울 수 있을 거라고 기대해본다. 상금을 타는 것도 중요하지만 현재는 실력을 쌓는데 집중하자.