Summary
The deployWithFactory
function does not send user's ether to the factory contract locking ether inside BiconomyMetaFactory
.
Root Cause
https://github.com/Cyfrin/2024-07-biconomy/blob/9590f25cd63f7ad2c54feb618036984774f3879d/contracts/factory/BiconomyMetaFactory.sol#L72
The deployWithFactory
calls factory address with low-level call
but it does not send msg.value
. BiconomyMetaFactory
does not have any ether recovery mechanism which means that all of the user's ether will be locked forever.
function deployWithFactory(address factory, bytes calldata factoryData) external payable returns (address payable createdAccount) {
require(factoryWhitelist[address(factory)], FactoryNotWhitelisted());
(bool success, bytes memory returnData) = factory.call(factoryData);
require(success, CallToDeployWithFactoryFailed());
assembly {
createdAccount := mload(add(returnData, 0x20))
}
}
Impact
User will lose all of the send ether using deployWithFactory
.
Mitigation
Send msg.value
to factory with low-level call
.
Example pseudocode:
function deployWithFactory(address factory, bytes calldata factoryData) external payable returns (address payable createdAccount) {
require(factoryWhitelist[address(factory)], FactoryNotWhitelisted());
- (bool success, bytes memory returnData) = factory.call(factoryData);
+ (bool success, bytes memory returnData) = factory.call{value: msg.value}(factoryData);
// Check if the call was successful
require(success, CallToDeployWithFactoryFailed());
// Decode the returned address
assembly {
createdAccount := mload(add(returnData, 0x20))
}
}