Closed code423n4 closed 1 year ago
0xSorryNotSorry marked the issue as primary issue
toshiSat marked the issue as sponsor confirmed
toshiSat marked the issue as disagree with severity
This finding is basically saying: "By commenting out the line responsible for sending Ether back" no ether is sent back. How can this happen in production?
Picodes marked the issue as unsatisfactory: Invalid
Lines of code
https://github.com/code-423n4/2023-03-asymmetry/blob/main/contracts/SafEth/SafEth.sol#L118
Vulnerability details
Impact
In all
withdraw()
functions of derivatives, there is no check for sending zero Ether back to thesafEth
contract. It is important to note that theaddress(msg.sender).call{value: 0}("")
function returnstrue
even when transferring a zero value.On the other hand, the
safEth
contract does not perform a zero check when receiving Ether from the derivatives. As a result, when a user calls theunstake()
function, if there is any issue while withdrawing from an external liquidity staking derivative contract, the user'ssafEth
tokens will be burnt without receiving any Ether compensation in return. This situation may lead to a partial or full loss of users' funds.Proof of Concept
The test attempts to make a regular call to the
stake()
function andunstake()
function. Afterward, it compares the Ether balance difference, which should be within 1% of the slippage loss.To emulate potential issues with one of the external liquidity staking derivatives, comment out the line https://github.com/code-423n4/2023-03-asymmetry/blob/main/contracts/SafEth/derivatives/Reth.sol#L108 in the
withdraw()
function ofReth.sol
like this:By commenting out the line responsible for sending Ether back, you can simulate a situation where the derivative fails to return the expected Ether amount. This will help you observe the impact on the
unstake()
function and ensure that the implemented mitigation steps are effective in preventing the burning ofsafEth
tokens.To test this scenario in Foundry, run the command
forge test -vv --match-test testFailUnstake
.The result will be a passed test with an error
Assertion Failed
. That means the user gets back less Ether than expected.Tools Used
VSCodium, Foundry
Recommended Mitigation Steps
One possible solution is to check the difference in Ether balance for each derivative within the
unstake()
function. This can be achieved by comparing the contract's Ether balance before and after calling thewithdraw()
function of the derivative. If the difference is zero, the contract should revert the transaction, preventing the burning ofsafEth
tokens. Modify theunstake()
function as follows: