diff --git a/contracts/src/v0.8/automation/ZKSyncAutomationForwarder.sol b/contracts/src/v0.8/automation/ZKSyncAutomationForwarder.sol index 350a4939b52..c13ba6af83e 100644 --- a/contracts/src/v0.8/automation/ZKSyncAutomationForwarder.sol +++ b/contracts/src/v0.8/automation/ZKSyncAutomationForwarder.sol @@ -14,6 +14,7 @@ uint256 constant PERFORM_GAS_CUSHION = 5_000; */ contract ZKSyncAutomationForwarder { error InvalidCaller(address); + event GasDetails(uint256 executionGas, uint256 gasPrice, uint256 pubdataGasSpent); /// @notice the user's target contract address address private immutable i_target; @@ -49,7 +50,9 @@ contract ZKSyncAutomationForwarder { if (success) { (, pubdataGasSpent) = abi.decode(returnData, (bytes, uint256)); } - gasUsed = g1 - gasleft() + pubdataGasSpent; + uint256 executionGas = g1 - gasleft(); + gasUsed = executionGas + pubdataGasSpent; + emit GasDetails(executionGas, tx.gasprice, pubdataGasSpent); if (gasUsed > gasAmount) { return (false, gasUsed); } diff --git a/contracts/src/v0.8/automation/testhelpers/LogUpkeepCounterSimple.sol b/contracts/src/v0.8/automation/testhelpers/LogUpkeepCounterSimple.sol new file mode 100644 index 00000000000..7c25ab4991e --- /dev/null +++ b/contracts/src/v0.8/automation/testhelpers/LogUpkeepCounterSimple.sol @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +struct Log { + uint256 index; + uint256 timestamp; + bytes32 txHash; + uint256 blockNumber; + bytes32 blockHash; + address source; + bytes32[] topics; + bytes data; +} + +contract LogUpkeepCounterSimple { + bytes32 sig1 = 0x3d53a39550e04688065827f3bb86584cb007ab9ebca7ebd528e7301c9c31eb5d; + bytes32 sig2 = 0x57b1de35764b0939dde00771c7069cdf8d6a65d6a175623f19aa18784fd4c6da; + bytes32 sig3 = 0x1da9f70fe932e73fba9374396c5c0b02dbd170f951874b7b4afabe4dd029a9c8; + bytes32 sig4 = 0x5121119bad45ca7e58e0bdadf39045f5111e93ba4304a0f6457a3e7bc9791e71; + + event PerformingUpkeep( + address indexed from, + uint256 initialBlock, + uint256 lastBlock, + uint256 previousBlock, + uint256 counter + ); + + /** + * @dev we include multiple event types for testing various filters, signatures, etc + */ + event Trigger(); // 0x3d53a39550e04688065827f3bb86584cb007ab9ebca7ebd528e7301c9c31eb5d + event Trigger(uint256 a); // 0x57b1de35764b0939dde00771c7069cdf8d6a65d6a175623f19aa18784fd4c6da + event Trigger(uint256 a, uint256 b); // 0x1da9f70fe932e73fba9374396c5c0b02dbd170f951874b7b4afabe4dd029a9c8 + event Trigger(uint256 a, uint256 b, uint256 c); // 0x5121119bad45ca7e58e0bdadf39045f5111e93ba4304a0f6457a3e7bc9791e71 + + uint256 public testRange; + uint256 public lastBlock; + uint256 public previousPerformBlock; + uint256 public initialBlock; + uint256 public counter; + + constructor(uint256 _testRange) { + testRange = _testRange; + previousPerformBlock = 0; + lastBlock = block.number; + initialBlock = 0; + counter = 0; + } + + function start() public { + // need an initial event to begin the cycle + emit Trigger(); + emit Trigger(1); + emit Trigger(1, 2); + emit Trigger(1, 2, 3); + } + + function checkLog(Log calldata log, bytes memory) external view returns (bool, bytes memory) { + require(eligible(), "not eligible"); + if (log.topics[0] == sig1 || log.topics[0] == sig2 || log.topics[0] == sig3 || log.topics[0] == sig4) { + return (true, abi.encode(log)); + } else { + revert("could not find matching event sig"); + } + } + + function performUpkeep(bytes calldata performData) external { + if (initialBlock == 0) { + initialBlock = block.number; + } + lastBlock = block.number; + counter = counter + 1; + previousPerformBlock = lastBlock; + emit PerformingUpkeep(tx.origin, initialBlock, lastBlock, previousPerformBlock, counter); + } + + function eligible() public view returns (bool) { + if (initialBlock == 0) { + return true; + } + + return (block.number - initialBlock) < testRange; + } + + function setSpread(uint256 _testRange) external { + testRange = _testRange; + initialBlock = 0; + counter = 0; + } +} diff --git a/contracts/src/v0.8/automation/testhelpers/UpkeepCounterNew.sol b/contracts/src/v0.8/automation/testhelpers/UpkeepCounterNew.sol new file mode 100644 index 00000000000..524a14e9bde --- /dev/null +++ b/contracts/src/v0.8/automation/testhelpers/UpkeepCounterNew.sol @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.16; + +contract UpkeepCounterNew { + event PerformingUpkeep( + address indexed from, + uint256 initialTimestamp, + uint256 lastTimestamp, + uint256 previousBlock, + uint256 counter + ); + + uint256 public testRange; + uint256 public interval; + uint256 public lastTimestamp; + uint256 public previousPerformBlock; + uint256 public initialTimestamp; + uint256 public counter; + bool public useMoreCheckGas; + bool public useMorePerformGas; + bool public useMorePerformData; + uint256 public checkGasToBurn; + uint256 public performGasToBurn; + bytes public data; + bytes public dataCopy; + + constructor() { + testRange = 1000000; + interval = 40; + previousPerformBlock = 0; + lastTimestamp = block.timestamp; + initialTimestamp = 0; + counter = 0; + useMoreCheckGas = false; + useMorePerformData = false; + useMorePerformGas = false; + checkGasToBurn = 5000000; + performGasToBurn = 5000000; + } + + function setPerformGasToBurn(uint256 value) public { + performGasToBurn = value; + } + + function setCheckGasToBurn(uint256 value) public { + checkGasToBurn = value; + } + + function setUseMoreCheckGas(bool _useMoreCheckGas) external { + useMoreCheckGas = _useMoreCheckGas; + } + + function setUseMorePerformGas(bool _useMorePerformGas) external { + useMorePerformGas = _useMorePerformGas; + } + + function setUseMorePerformData(bool _useMorePerformData) external { + useMorePerformData = _useMorePerformData; + } + + function setData(bytes calldata _data) external { + data = _data; + } + + function checkUpkeep(bytes calldata) external view returns (bool, bytes memory) { + if (useMoreCheckGas) { + uint256 startGas = gasleft(); + while (startGas - gasleft() < checkGasToBurn) {} // burn gas + } + + return (eligible(), data); + } + + function performUpkeep(bytes calldata performData) external { + if (useMorePerformGas) { + uint256 startGas = gasleft(); + while (startGas - gasleft() < performGasToBurn) {} // burn gas + } + + if (initialTimestamp == 0) { + initialTimestamp = block.timestamp; + } + lastTimestamp = block.timestamp; + counter = counter + 1; + dataCopy = performData; + emit PerformingUpkeep(tx.origin, initialTimestamp, lastTimestamp, previousPerformBlock, counter); + previousPerformBlock = lastTimestamp; + } + + function eligible() public view returns (bool) { + if (initialTimestamp == 0) { + return true; + } + + return (block.timestamp - initialTimestamp) < testRange && (block.timestamp - lastTimestamp) >= interval; + } + + function setSpread(uint256 _testRange, uint256 _interval) external { + testRange = _testRange; + interval = _interval; + initialTimestamp = 0; + counter = 0; + } +}