code4rena-2023-12-shell-protocol-l02
[L-02] Interactions is susceptible to read-only reentrancy
Summary
인터렉션이 끝난 후에야 Ocean 토큰을 소각하기 때문에 read-only 재진입이 가능하다.
Keyword
read-only reentrancy
Vulnerability
인터렉션이 끝난 후에야 Ocean 토큰을 소각 또는 민팅하기 때문에, 재진입의 여지가 있다.
@> (inputToken, inputAmount, outputToken, outputAmount) = _executeInteraction(
interaction, interactionType, externalContract, specifiedToken, interaction.specifiedAmount, userAddress
);
}
// if _executeInteraction returned a positive value for inputAmount,
// this amount must be deducted from the user's Ocean balance
if (inputAmount > 0) {
// since uint, same as (inputAmount != 0)
@> _burn(userAddress, inputToken, inputAmount);
}
// if _executeInteraction returned a positive value for outputAmount,
// this amount must be credited to the user's Ocean balance
if (outputAmount > 0) {
// since uint, same as (outputAmount != 0)
@> _mint(userAddress, outputToken, outputAmount);
}ERC721 토큰을 unwrap 하는 상황을 생각해보자. 먼저 _executeInteraction 에서 유저에게 ERC721을 돌려준다. 이 때 safeTransferFrom 를 사용하므로 토큰 수신자가 컨트랙트라면 리시브 훅이 실행될 것이다. 아직 인터렉션이 끝나지 않았으므로, 리시브 훅에서는 ERC721과 shERC721을 둘 다 가진 상태가 된다. shERC721의 소각은 인터렉션이 끝난 후 실행되기 때문이다.
function _erc721Unwrap(address tokenAddress, uint256 tokenId, address userAddress, uint256 oceanId) private {
@> IERC721(tokenAddress).safeTransferFrom(address(this), userAddress, tokenId);
emit Erc721Unwrap(tokenAddress, tokenId, userAddress, oceanId);
}향후 대출/차입같은 상호작용이 더 많아진다면 read-only 재진입으로 인한 이슈가 발생할 수 있다.
Impact
read-only 재진입이 가능하다.
Mitigation
소각은 먼저 하는 게 좋다.
tags: bughunting, shell protocol, smart contract, solidity, reentrancy, severity low