際限のないループ処理
code-423n4/2022-03-joyn-findings#6
- 誰でも配列のアイテムを追加できる
- その配列の長さに応じてループ処理をしている
/// Loop
for (uint256 i = 0; i < currentWindow; i++) {
if (!isClaimed(msg.sender, i)) {
setClaimed(msg.sender, i);
amount += scaleAmountByPercentage(
balanceForWindow[i],
percentageAllocation
);
}
}
/// Add item for array
function incrementWindow(uint256 royaltyAmount) public returns (bool) {
uint256 wethBalance;
/* ... */
// here
balanceForWindow.push(royaltyAmount);
currentWindow += 1;
emit WindowIncremented(currentWindow, royaltyAmount);
return true;
}
- Eve が
incrementWindow()
を実行して currentWindow の配列を 1000 まで増加させる currentWindow
を削除する関数がないため、増加するしかない- ループを実行するとガス代がかかりすぎ、ブロックガスリミットを超えるためトランザクションが revert される
- 最終的にこのループを含む
claimForAllWindows()
が使用できなくなる(Denial of Service = サービスの妨害
- 配列の要素の最大を決める
uint256 constant MAX_CURRENT_WINDOW = 100;
function incrementWindow(uint256 royaltyAmount) public returns (bool) {
/* ... */
require(balanceForWindow.length < MAX_CURRENT_WINDOW,"TOO MUCH"); // here
balanceForWindow.push(royaltyAmount);
currentWindow += 1;
}
incrementWindow
を実行できるユーザーを制限する
mapping(address=>bool) whitelist;
modifier onlyWhitelist {
require(whitelist[msg.sender]);
_;
}
function incrementWindow(uint256 royaltyAmount) public /* add */ onlyWhitelist returns (bool) {
/* ... */
require(balanceForWindow.length < MAX_CURRENT_WINDOW,"TOO MUCH"); // here
balanceForWindow.push(royaltyAmount);
currentWindow += 1;
}
code-423n4/2022-05-aura-findings#197