ETH Surplus Unaccounted for in batchCreateTriple Function #78
Description
Github username: --
Twitter username: --
Submission hash (on-chain): 0x45af594e37907786efc19eea5046d4b897518936ba6dc1ee0e011e4b1bfa26dd
Severity: high
Description:
Description
In the batchCreateTriple
function of the EthMultiVault contract, there's an issue where potential ETH surplus from the division of msg.value
by the number of triples is not accounted for or returned to the user. This can lead to small amounts of ETH being trapped in the contract, inaccessible to both users and the protocol.
Attack Scenario
While not a direct security vulnerability, this issue can lead to the following problems:
- Users consistently lose small amounts of ETH when creating multiple triples.
- Over time, these small amounts can accumulate in the contract without any mechanism to retrieve them.
- In extreme cases with many transactions, the accumulated ETH could become significant.
Attachments
-
Proof of Concept (PoC) File
Intuition-0x538dbadc50cc87b281cd655f1edbc6ebda02a66a/src/EthMultiVault.sol
Lines 544 to 570 in b2e422f
-
Revised Code File (Optional)
function batchCreateTriple(
uint256[] calldata subjectIds,
uint256[] calldata predicateIds,
uint256[] calldata objectIds
) external payable nonReentrant whenNotPaused returns (uint256[] memory) {
if (subjectIds.length != predicateIds.length || subjectIds.length != objectIds.length) {
revert Errors.MultiVault_ArraysNotSameLength();
}
uint256 length = subjectIds.length;
uint256 tripleCost = getTripleCost();
if (msg.value < tripleCost * length) {
revert Errors.MultiVault_InsufficientBalance();
}
uint256 valuePerTriple = msg.value / length;
uint256 protocolDepositFeeTotal;
uint256[] memory ids = new uint256[](length);
for (uint256 i = 0; i < length; i++) {
uint256 protocolDepositFee;
(ids[i], protocolDepositFee) = _createTriple(
subjectIds[i],
predicateIds[i],
objectIds[i],
valuePerTriple
);
protocolDepositFeeTotal += protocolDepositFee;
}
uint256 totalFeesForProtocol = tripleConfig.tripleCreationProtocolFee * length + protocolDepositFeeTotal;
_transferFeesToProtocolVault(totalFeesForProtocol);
// Calculate and refund any surplus
uint256 surplus = msg.value - (valuePerTriple * length);
if (surplus > 0) {
(bool success,) = msg.sender.call{value: surplus}("");
require(success, "Surplus refund failed");
}
return ids;
}