code4rena-2023-01-biconomy-l04
[L-04] Gas griefing/theft is possible on unsafe external call
Summary
(bool success,) = dest.call{value:amount}(""); 와 같이 호출하더라도 return 값이 메모리로 복사되기 때문에 가스 절약을 위해서라면 어셈블리로 호출하여 return 값을 버려야 한다.
Keyword
gas optimization
Vulnerability
- contracts/smart-contract-wallet/SmartAccount.sol#L451
- contracts/smart-contract-wallet/SmartAccount.sol#L261
- contracts/smart-contract-wallet/SmartAccount.sol#L285
- contracts/smart-contract-wallet/SmartAccount.sol#L527
- contracts/smart-contract-wallet/aa-4337/core/EntryPoint.sol#L37
- contracts/smart-contract-wallet/aa-4337/core/StakeManager.sol#L106
- contracts/smart-contract-wallet/aa-4337/core/StakeManager.sol#L120
- contracts/smart-contract-wallet/BaseSmartAccount.sol#L108
(bool success,) = dest.call{value:amount}(""); 와 같이 return value를 날리더라도 내부적으로 return value를 메모리에 복사한다고 한다.
Did you know that the normal “(bool success, bytes memory returnData) = target.call()” automatically copies the return data to memory even if you omit the returnData variable? If a relayer executes transactions with such calls it can lead to a gas-griefing attack.
이로 인해 사용하지 않는 변수를 불필요하게 복사하고, gas를 낭비한다. 이를 피하기 위해서는 어셈블리로 call을 호출하고, return 값은 버리도록 해야한다.
다음과 같이 out과 outsize를 0로 설정하면 가스를 절약할 수 있다.
assembly {
success := call(gas(), dest, amount, 0, 0)
}Impact
불필요하게 gas를 낭비한다.
Mitigation
assembly {
success := call(gas(), dest, amount, 0, 0)
}위와 같이 어셈블리로 호출하여 리턴값을 버린다.
Memo
gas optimization 으로 처리해도 될 것 같은데 Gas griefing/theft 로 엮어서 low를 받았다.
tags: bughunting, smart contract, biconomy, account abstraction, erc4337, gas, solidity assembly, gas optimization, wallet, severity low