Dria

Swan
NFTHardhat
21,000 USDC
View results
Submission Details
Severity: high
Invalid

Use of `.transfer()` in `withdrawPlatformFees` will not work on zkSync

Github

https://github.com/Cyfrin/2024-10-swan-dria/blob/c8686b199daadcef3161980022e12b66a5304f8e/contracts/swan/BuyerAgent.sol#L276

https://github.com/Cyfrin/2024-10-swan-dria/blob/c8686b199daadcef3161980022e12b66a5304f8e/contracts/llm/LLMOracleCoordinator.sol#L376

Summary

The Dria protocol uses ERC20's .transfer() method in multiple critical functions which will not work correctly when deployed on zkSync due to the L2's gas metering mechanism. This could result in failed transfers and stuck funds.

Vulnerability Details

I talked to client and they do have plans for deploying the protocol to zkSync, however below instances use .transfer() to transfer funds to users, which does not work on zkSync. This causes funds to be stuck in the contract. According to zkSync docs:

"Avoid using payable(addr).send(x)/payable(addr).transfer(x) because the 2300 gas stipend may not be enough for such calls, especially if it involves state changes that require a large amount of L2 gas for data."

Instances where .transfer is used:

// In LLMOracleCoordinator.sol
function withdrawPlatformFees() public onlyOwner {
feeToken.transfer(owner(), feeToken.balanceOf(address(this)));
}
// In BuyerAgent.sol
function withdraw(uint96 _amount) public onlyAuthorized {
swan.token().transfer(owner(), _amount);
}
// In Swan.sol
function transferRoyalties(AssetListing storage asset) internal {
token.transfer(asset.buyer, buyerFee - driaFee);
token.transfer(owner(), driaFee);
}
function purchase(address _asset) external {
token.transfer(listing.seller, listing.price);
}

Impact

  • HIGH

  • Failed token transfers due to insufficient gas stipend

  • Funds could get stuck in contracts

  • Core protocol operations (purchases, royalty payments, withdrawals) could fail

  • Could completely break protocol functionality on zkSync

Likelihood

  • HIGH

  • Will occur consistently on zkSync deployment

  • Affects multiple core functions

  • No fallback mechanisms in place

Proof of Concept

  1. Deploy protocol on zkSync

  2. Attempt any operation using .transfer()

  3. Transaction will fail due to insufficient gas stipend

  4. Funds remain stuck in contract

Recommendation

Consider using .call() for funds transfer as instructed in zksync doc.

Updates

Lead Judging Commences

inallhonesty Lead Judge 8 months ago
Submission Judgement Published
Invalidated
Reason: Lack of quality

Appeal created

0xtheblackpanther Submitter
8 months ago
inallhonesty Lead Judge
8 months ago
inallhonesty Lead Judge 8 months ago
Submission Judgement Published
Invalidated
Reason: Lack of quality

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.