code4rena-2022-11-blur-exchange-m01
[M-01] Yul call return value not checked
Summary
어셈블리로 호출한 call의 결과를 확인하지 않아 실제로 ETH를 돌려받지 못해도 revert 되지 않는다. 구매자가 구매 실패건에 대한 ETH를 환급받지 못해 손해를 보게 된다.
Keyword
assembly, call, return value, receive, fallback
Vulnerability
_returnDust 함수는 거래 후 남은 ETH를 컨트랙트콜을 한 caller에게 돌려주는 역할을 한다. 여러개의 거래를 처리할 때, 중간에 거래가 실패해도 트랜잭션이 실패하지 않도록 처리되었다. 그리고 남은 거래를 전부 처리하면 원래 실패한 거래에 사용되어야 했던, 남은 ETH를 호출자에게 돌려줘야 한다.
이 때, _returnDust에서 어셈블리로 호출한 call의 리턴 값을 확인하지 않는다. call의 실패 여부를 callStatus에 받지만 이를 확인하고 핸들링하지 않는다. 만약 caller가 컨트랙트이고, receive나 fallback 함수를 구현해두지 않아 토큰을 받을 수 없다면 이 콜은 실패한다.
function _returnDust() private {
uint256 _remainingETH = remainingETH;
assembly {
if gt(_remainingETH, 0) {
let callStatus := call(
gas(),
caller(),
selfbalance(),
0,
0,
0,
0
)
}
}
}이 경우 caller는 남은 ETH를 돌려받지 못한다.
Impact
구매자가 구매 실패건에 대한 ETH를 환급받지 못해 손해를 보게 된다.
Mitigation
+ error ReturnDustFail();
function _returnDust() private {
uint256 _remainingETH = remainingETH;
+ bool success;
assembly {
if gt(_remainingETH, 0) {
- let callStatus := call(
+ success := call(
gas(),
caller(),
selfbalance(),
0,
0,
0,
0
)
}
}
+ if (!success) revert ReturnDustFail();
}tags: bughunting, blur exchange, smart contract, solidity, nft marketplace, native token, solidity receive, solidity fallback, solidity assembly, severity medium