Summary
L1Sender::sendMintMessage allows to burn ETH via refundTo_ parameter making impossible to recover it.
Setting refundTo_ parameter to Zero Address will burn ETH forever
Vulnerability Details
The vulnerability exists in L1Sender::sendMintMessage method. It doesnt check refundTo_ parameter
If zero address is used then all the gas not used will be burned
function sendMintMessage(address user_, uint256 amount_, address refundTo_) external payable onlyDistribution {
ILayerZeroEndpoint(config.gateway).send{value: msg.value}(
config.receiverChainId,
receiverAndSenderAddresses_,
payload_,
payable(refundTo_),
Impact
All remainig eth used in the function call will be burned forever, and wont be able to recover.
To show this add the following test case in test/L1Sender.test.ts file, under the sendMintMessage section:
describe('sendMintMessage', () => {
it('should send mint message2', async () => {
console.log("OWNER BEFORE",await ethers.provider.getBalance(OWNER.address));
console.log("ZERO_ADDR BEFORE",await ethers.provider.getBalance(ZERO_ADDR));
await l1Sender.sendMintMessage(SECOND, '999', ZERO_ADDR, { value: ethers.parseEther('0.1') });
console.log("OWNER ETH BALANCE AFTER",await ethers.provider.getBalance(OWNER.address));
console.log("ZERO_ADDR AFTER",await ethers.provider.getBalance(ZERO_ADDR));
expect(await rewardToken.balanceOf(SECOND)).to.eq('999');
});
Observe the remaining eth is transfered to Zero address
Tools Used
Manual review
Recommendations
Implement a zero address check on L1Sender::sendMintMessage
function sendMintMessage(address user_, uint256 amount_, address refundTo_) external payable onlyDistribution {
require(refundTo_ != address(0), "L1S: invalid refundTo_");
ILayerZeroEndpoint(config.gateway).send{value: msg.value}(
config.receiverChainId,
receiverAndSenderAddresses_,
payload_,
payable(refundTo_),