DeFiFoundry
60,000 USDC
View results
Submission Details
Severity: low
Valid

Orders wont be filled in fillMarketOrder becuase of lack of payable modifier

Summary

in the SettlementBranch::fillMarketOrderdown the call stack it makes a call to verify offchain prices, to get the bid and ask prices, down that call stack it makes a call to the chainlink verifier proxy, which is a payable function, it is payable becuase the verifier takes eth to verify this prices, but at fillMarketOrderthe entry to this process the function itself is not payable, which means any attempt to try to verify the prices will always fail and revert.

Vulnerability Details

in the SettlementBranch::fillMarketOrderwhen it is called to fill orders, it does the necessary calculations, and then it tries to verify the priceData using the SettlementConfiguration::verifyOffchainPrice, this verifies and returns the validated bid and ask prices, inside that function it makes an internal call to verifyDataStreamsReport to verify the data stream report, the snippet as shown below

SettlementConfiguration::verifyDataStreamsReport

function verifyDataStreamsReport(
DataStreamsStrategy memory dataStreamsStrategy,
bytes memory signedReport
)
internal
returns (bytes memory verifiedReportData)
{
IVerifierProxy chainlinkVerifier = dataStreamsStrategy.chainlinkVerifier;
bytes memory reportData = ChainlinkUtil.getReportData(signedReport);
(FeeAsset memory fee) = ChainlinkUtil.getEthVericationFee(chainlinkVerifier, reportData);
verifiedReportData = ChainlinkUtil.verifyReport(chainlinkVerifier, fee, signedReport);
}

The function clearly show here that there is an attached fee and it actually gets it from the util contract, to verification and it tries to make the call to the ChainlinkVerifer, and it passes along the fee gotten as shown below

function getEthVericationFee(
IVerifierProxy chainlinkVerifier,
bytes memory reportData
)
internal
returns (FeeAsset memory fee)
{
IFeeManager chainlinkFeeManager = chainlinkVerifier.s_feeManager();
address feeTokenAddress = chainlinkFeeManager.i_nativeAddress();
(fee,,) = chainlinkFeeManager.getFeeAndReward(address(this), reportData, feeTokenAddress);
}
function verifyReport(
IVerifierProxy chainlinkVerifier,
FeeAsset memory fee,
bytes memory signedReport
)
internal
returns (bytes memory verifiedReportData)
{
verifiedReportData = chainlinkVerifier.verify{ value: fee.amount }(signedReport, abi.encode(fee.assetAddress));
}

The getEthVericationFee gets the fees from the fee manager and then the verifyReport is also called using that fee and it makes a call to the chainlinkVerifier by passing along a value a fee for the verification, when we check the verifier contract we see that it is a proxy that redirects the call and it is actually a payable function as shown below

interface IVerifierProxy {
function verify(
bytes calldata payload,
bytes calldata parameterPayload
)
external
payable
returns (bytes memory verifierResponse);
function s_feeManager() external view returns (IFeeManager);
}

Because the fillMarketOrder function itself does not have a payable modifier itself it will not be able to pay for this verification

Impact

filling orders by keepers is one of the main functionality in zaros, if orders can be filled then the protocol does not work at all

Tools Used

Manual Review

Recommendations

Add a payable modifer to the fillMarketOrder function

Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

No means for the PerpEngine to receive native to pay the Chainlink Verifier in case Chainlinks charges fees to the protocol

Support

FAQs

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