pashov-2023-01-bearcave-m01

[M-01] The fulfillRandomWords method might revert with out of gas error

보고서

Summary

VRF fulfillRandomWords 콜백이 revert 되기 쉽다. VRF과의 통합에 문제가 발생하여 프로토콜이 망가진다.

Keyword

chainlink, vrf, gas limit, arithmetic error, rounding error, precision

Vulnerability

Chainlink VRF 콜백인 fulfillRandomWords 함수에서 배열을 순회한다. 이 때, external 콜도 실행된다. 이는 잠재적으로 많은 가스를 소비할 수 있드며, gas limit에 도달하면 fulfillRandomWords 함수가 revert 될 것이다.

이는 VRF와의 통합에 문제를 일으킬 수 있다. Chainlink 문서에서도 콜백에서는 랜덤 값만 저장하고 끝내는 등 작업을 최소화하여 revert 되지 않도록 주의하라고 한다.

또한 다음 코드 역시 문제이다. (콜백에 존재)

if (party.assetChainId != getChainId() && address(honeyJarPortal) != address(0) && address(this).balance != 0) {
    uint256 sendAmount = address(this).balance / party.checkpoints.length;
    honeyJarPortal.sendFermentedJars{value: sendAmount}(
        address(this), party.assetChainId, party.bundleId, fermentedJars
    );
}

party.assetChainId != getChainId() && address(honeyJarPortal) != address(0) 조건을 만족할 때, 나머지 조건인 address(this).balance != 0는 굉장히 달성하기 쉽다. 누구나 1 wei를 컨트랙트에 보내두면 되기 때문이다.

콜백 내 이 로직을 트리거하면 더 많은 external 콜을 시킬 수 있으므로 더 많은 가스를 소모한다. sendAmount는 0으로 반올림 될 수 있기 때문에, sendFermentedJars는 거의 확실하게 revert 될 수 있다.

Impact

영향도: 높음. 랜덤값이 제공되지 않기 때문. 일어날 확률: 적음. 가스 설정이 잘못되어야 한다는 조건이 필요.

Mitigation

fulfillRandomWords 콜백에서 받은 랜덤값을 캐싱하고, 다른 계정을 이용하여 로직 함수를 따로 호출한다. 또한 sendFermentedJars를 호출하기에 충분한 잔액을 가지고 있는지 (0으로 반올림되지 않는지) 확인한다.


tags: bughunting, bearcave, smart contract, solidity, chainlink, chainlink vrf, arithmetic error, rounding error, severity medium