51129 sc low boringvault proxies do not support smart contract wallets
Submitted on Jul 31st 2025 at 12:18:30 UTC by @holydevoti0n for Attackathon | Plume Network
Report ID: #51129
Report Type: Smart Contract
Report severity: Low
Target: https://github.com/immunefi-team/attackathon-plume-network-nucleus-boring-vault/blob/main/src/base/Roles/TellerWithMultiAssetSupportPredicateProxy.sol
Impacts:
Contract fails to deliver promised returns, but doesn't lose value
Description
Vulnerability Details
The TellerWithMultiAssetSupportPredicateProxy uses the PredicateClient to verify signatures.
function deposit(
ERC20 depositAsset,
uint256 depositAmount,
uint256 minimumMint,
address recipient,
CrossChainTellerBase teller,
PredicateMessage calldata predicateMessage
)
external
nonReentrant
returns (uint256 shares)
{
if (paused()) {
revert TellerWithMultiAssetSupportPredicateProxy__Paused();
}
bytes memory encodedSigAndArgs = abi.encodeWithSignature("deposit()");
// @audit-issue the signature method is incompatible with smart wallets that use eip-1271.
@> if (!_authorizeTransaction(predicateMessage, encodedSigAndArgs, msg.sender, 0)) {
revert TellerWithMultiAssetSupportPredicateProxy__PredicateUnauthorizedTransaction();
}
... The problem is _authorizeTransaction does not support smart contract wallets:
https://github.com/predicatelabs/predicate-contracts/blob/32d16b289752951c6dfe51b7efd2ec1c17b63e5c/src/ServiceManager.sol#L335
function validateSignatures(
Task calldata _task,
address[] memory signerAddresses,
bytes[] memory signatures
) external returns (bool isVerified) {
...
@> address recoveredSigner = ECDSA.recover(messageHash, signatures[i]);This will lead the transaction to revert because, with EIP-7702, it is now possible for addresses to have code.length > 0 but still use their private keys to sign;
Impact Details
Smart contract wallets cannot interact with the TellerWithMultiAssetSupportPredicateProxy as ECDSA.recover from _authorizeTransaction will cause the transaction to revert.
Recommendation
References
Proof of Concept
Predicate constructs hash including smart contract wallet address
The hash built in PredicateClient.ServiceManager.validateSignatures utilises the smart contract wallet address to compare the hash against the signature:
https://github.com/predicatelabs/predicate-contracts/blob/32d16b289752951c6dfe51b7efd2ec1c17b63e5c/src/ServiceManager.sol#L335
@> bytes32 messageHash = hashTaskSafe(_task);
...
@> address recoveredSigner = ECDSA.recover(messageHash, signatures[i]);
function hashTaskSafe(
Task calldata _task
) public view returns (bytes32) {
return keccak256(
abi.encode(
_task.taskId,
@> _task.msgSender, // @audit smart contract wallet address
msg.sender,
_task.value,
_task.encodedSigAndArgs,
_task.policyID,
_task.quorumThresholdCount,
_task.expireByTime
)
);
}Was this helpful?