Summary
The contract can assign house prices to the wrong property because it doesn’t tie Chainlink request IDs to house IDs. If two requests are sent within 5 minutes, the second response might arrive first and overwrite the price for the wrong house.
Vulnerability Details
The RAACHousePriceOracle uses Chainlink Functions to fetch house prices. The process works in two steps:
sendRequest sends a request with a houseId in args[0], stored in lastHouseId via _beforeFulfill.
fulfillRequest processes the response and assigns the price to lastHouseId.
Chainlink Functions can take up to 5 minutes to respond (per docs). If two requests are sent before the first response arrives, lastHouseId gets overwritten by the second request. When responses come back, they’re processed in whatever order they arrive, not the order they were sent. For example:
Request 1: houseId = 1, sets lastHouseId = 1.
Request 2: houseId = 2, overwrites lastHouseId = 2.
Response 2 arrives first (price = 200), sets price of house 2.
Response 1 arrives second (price = 100), overwrites price of house 2 instead of house 1.
This mixes up prices because fulfillRequest uses lastHouseId without checking which request it belongs to.
https://docs.chain.link/chainlink-functions/resources/service-limits
Impact
Wrong prices get assigned to houses. This messes up NFT valuations tied to those prices, leading to incorrect loan amounts. A borrower could get too much or too little based on a swapped price, costing money or breaking the system’s trust.
Tools Used
Manual review of RAACHousePriceOracle and BaseChainlinkFunctionsOracle code, plus Chainlink Functions docs on service limits.
Recommendations
Map Request ID to House ID: Store houseId with each requestId in a mapping. Use it in fulfillRequest to set the right price.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.