All bridged funds will be lost for the users using the account abstraction wallet
mediumLines of code
https://github.com/code-423n4/2023-09-ondo/blob/47d34d6d4a5303af5f46e907ac2292e6a7745f6c/contracts/bridge/SourceBridge.sol#L61-L82 https://github.com/code-423n4/2023-09-ondo/blob/47d34d6d4a5303af5f46e907ac2292e6a7745f6c/contracts/bridge/DestinationBridge.sol#L85-L114
Vulnerability details
Impact
Users with account abstraction wallets have different address across different chains for same account, so if someone using account abstraction wallet bridge the asset, assets will be minted to wrong address and lost permanently
Proof of Concept
Account abstraction wallet have been on the rise for quite a time now and have alot of users, just look at the figures by safe wallet (one of the account abstraction wallet)

4.4 million users and 5.4 billion assets, there is very high risk that safe wallet users will try to bridge the assets and lost them.
Now look at the codebase and understand how the assets will be lost.
In source bridge in burnAndCallAxelar we construct the payload as follow :
here we can see the payload passes msg.sender as receiving address on other chain assuming that user have same address across all the evm chains, which is not the case if user is using the account abstraction wallet
soliditybytes memory payload = abi.encode(VERSION, msg.sender, amount, nonce++);
and than call the following function passing the payload, which calls the callContract function passing the payload to axelar network
solidityfunction _payGasAndCallCotract( string calldata destinationChain, string memory destContract, bytes memory payload ) private { GAS_RECEIVER.payNativeGasForContractCall{value: msg.value}( address(this), destinationChain, destContract, payload, msg.sender ); // Send all information to AxelarGateway contract. AXELAR_GATEWAY.callContract(destinationChain, destContract, payload); }
Than on the destination any axelar node will call the excute() function passing in the payload and the tokens will be minted to account abstraction wallet address of the source chain but on destination same person will not be the owner of that address, and hence tokens are permanently lost
solidityfunction _execute( string calldata srcChain, string calldata srcAddr, bytes calldata payload ) internal override whenNotPaused { (bytes32 version, address srcSender, uint256 amt, uint256 nonce) = abi .decode(payload, (bytes32, address, uint256, uint256)); if (version != VERSION) { revert InvalidVersion(); } if (chainToApprovedSender[srcChain] == bytes32(0)) { revert ChainNotSupported(); } // each chain have only on approved sender that is the source bridge contract. if (chainToApprovedSender[srcChain] != keccak256(abi.encode(srcAddr))) { revert SourceNotSupported(); } if (isSpentNonce[chainToApprovedSender[srcChain]][nonce]) { revert NonceSpent(); } isSpentNonce[chainToApprovedSender[srcChain]][nonce] = true; // same payload would have the same txhash bytes32 txnHash = keccak256(payload); txnHashToTransaction[txnHash] = Transaction(srcSender, amt); _attachThreshold(amt, txnHash, srcChain); _approve(txnHash); _mintIfThresholdMet(txnHash); emit MessageReceived(srcChain, srcSender, amt, nonce); }
Tools Used
Manual reviewing with some googling on different addresses across chains and have also read already somewhere in some contest, just could not find that report now.
Recommended Mitigation Steps
Give the user to pass in the address the tokens should be minted to on the destination bridge. And pass in the warning for account abstraction wallet holders to not to pass the same wallet. Some wallets may follow the deterministic deployment approach to have same address, but as safe explains that grantees nothing as each chain have its own different state and opcode differences so even deterministic approach may generate different addresses.
Assessed type
Invalid Validation
