Skip to content

Commit

Permalink
(fix): callback gasUsed should not count gasForCallExactCheck (#10104)
Browse files Browse the repository at this point in the history
* (fix): callback gasUsed should not count gasForCallExactCheck

* (test): Add FaultyClient test

* rename testhelper to FunctionsClientWithEmptyCallback
  • Loading branch information
justinkaseman authored Aug 8, 2023
1 parent 78d6113 commit fa811af
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 3 deletions.
3 changes: 2 additions & 1 deletion contracts/src/v0.8/functions/dev/1_0_0/FunctionsRouter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -427,8 +427,9 @@ contract FunctionsRouter is IFunctionsRouter, FunctionsSubscriptions, Pausable,
}
// call and report whether we succeeded
// call(gas,addr,value,argsOffset,argsLength,retOffset,retLength)
let gasBeforeCall := gas()
success := call(callbackGasLimit, client, 0, add(encodedCallback, 0x20), mload(encodedCallback), 0, 0)
gasUsed := sub(g, gas())
gasUsed := sub(gasBeforeCall, gas())

// limit our copy to MAX_CALLBACK_RETURN_BYTES bytes
let toCopy := returndatasize()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.6;

import {ITermsOfServiceAllowList} from "../../../dev/1_0_0/accessControl/interfaces/ITermsOfServiceAllowList.sol";
import {IFunctionsSubscriptions} from "../../../dev/1_0_0/interfaces/IFunctionsSubscriptions.sol";

import {FunctionsRequest} from "../../../dev/1_0_0/libraries/FunctionsRequest.sol";
import {FunctionsClient} from "../../../dev/1_0_0/FunctionsClient.sol";

contract FunctionsClientWithEmptyCallback is FunctionsClient {
using FunctionsRequest for FunctionsRequest.Request;

event SendRequestInvoked(bytes32 requestId, string sourceCode, uint64 subscriptionId);
event FulfillRequestInvoked(bytes32 requestId, bytes response, bytes err);

constructor(address router) FunctionsClient(router) {}

function sendSimpleRequestWithJavaScript(
string memory sourceCode,
uint64 subscriptionId,
bytes32 donId,
uint32 callbackGasLimit
) public returns (bytes32 requestId) {
FunctionsRequest.Request memory request;
request.initializeRequestForInlineJavaScript(sourceCode);
bytes memory requestData = FunctionsRequest.encodeCBOR(request);
requestId = _sendRequest(requestData, subscriptionId, callbackGasLimit, donId);
emit SendRequestInvoked(requestId, sourceCode, subscriptionId);
}

function fulfillRequest(bytes32 requestId, bytes memory response, bytes memory err) internal override {}
}
52 changes: 52 additions & 0 deletions contracts/test/v0.8/functions/v1/FunctionsClient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,3 +173,55 @@ describe('Functions Client', () => {
})
})
})

describe('Faulty Functions Client', () => {
it('can complete requests with an empty callback', async () => {
const clientWithEmptyCallbackTestHelperFactory =
await ethers.getContractFactory(
'src/v0.8/functions/tests/1_0_0/testhelpers/FunctionsClientWithEmptyCallback.sol:FunctionsClientWithEmptyCallback',
roles.consumer,
)

const clientWithEmptyCallback =
await clientWithEmptyCallbackTestHelperFactory
.connect(roles.consumer)
.deploy(contracts.router.address)

const subscriptionId = await createSubscription(
roles.subOwner,
[clientWithEmptyCallback.address],
contracts.router,
contracts.accessControl,
contracts.linkToken,
)
const tx = await clientWithEmptyCallback.sendSimpleRequestWithJavaScript(
'function run(){return response}',
subscriptionId,
ids.donId,
20_000,
)
const { events } = await tx.wait()
const requestId = getEventArg(events, 'RequestSent', 0)
await expect(tx)
.to.emit(clientWithEmptyCallback, 'RequestSent')
.withArgs(requestId)

const response = stringToBytes('response')
const error = stringToBytes('')
const oracleRequestEvent = await contracts.coordinator.queryFilter(
contracts.coordinator.filters.OracleRequest(),
)
const onchainMetadata = oracleRequestEvent[0].args?.['commitment']
const report = await encodeReport(
ethers.utils.hexZeroPad(requestId, 32),
response,
error,
onchainMetadata,
stringToBytes(''),
)
await expect(contracts.coordinator.callReport(report))
.to.emit(contracts.coordinator, 'OracleResponse')
.withArgs(requestId, await roles.defaultAccount.getAddress())
.to.emit(contracts.router, 'RequestProcessed')
})
})
Loading

0 comments on commit fa811af

Please sign in to comment.