code4rena-2021-06-pooltogether-m07
[M-07] Using transferFrom on ERC721 tokens
Summary
CA에게 ERC721을 transferFrom로 보내는 경우 컨트랙트에 ERC721을 꺼내는 기능이 없다면 영원히 꺼낼 수 없으므로 safeTransferFrom로 ERC721을 받을 준비가 된 CA에게만 리워드를 주도록 하자.
Keyword
erc721, safeTransferFrom
Vulnerability
PrizePool.awardExternalERC721 함수는 ControlledToken이 아닌 외부 토큰 중, ERC721을 이용하여 복권 당첨 리워드를 제공하는 함수이다. ERC721 토큰을 이동할 때 safeTransferFrom 대신 transferFrom 함수를 이용했다. 만약 당첨자 주소가 CA이고, 이 컨트랙트에서 ERC721 리시브 훅을 구현하지 않았다면 받은 ERC721을 꺼낼 수 없을 것이다.
function awardExternalERC721(
address to,
address externalToken,
uint256[] calldata tokenIds
)
external override
onlyPrizeStrategy
{
...
for (uint256 i = 0; i < tokenIds.length; i++) {
IERC721Upgradeable(externalToken).transferFrom(address(this), to, tokenIds[i]);
}
...
}Impact
리워드로 받은 ERC721을 꺼낼 수 없어 lock된다.
Mitigation
ERC721 이동 시 transferFrom 대신 safeTransferFrom를 사용한다. 다만 당첨자가 악의적으로 ERC721을 받기를 거부하는 DoS가 발생할 수 있으므로, try-catch문으로 완화하자.
Memo
주최자측은 low 심각도라 했지만 심판이 medium으로 동의했다.
tags: bughunting, pooltogether, smart contract, solidity, erc721, severity medium