Skip to content

Commit

Permalink
update auto registry 2.1 to include 2.0.2 changes (#8967)
Browse files Browse the repository at this point in the history
  • Loading branch information
RyanRHall authored Apr 17, 2023
1 parent 4450035 commit b8279a5
Show file tree
Hide file tree
Showing 4 changed files with 401 additions and 218 deletions.
26 changes: 16 additions & 10 deletions contracts/src/v0.8/dev/automation/2_1/KeeperRegistry2_1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ contract KeeperRegistry2_1 is

/**
* @notice versions:
* - KeeperRegistry 2.0.2: pass revert bytes as performData when target contract reverts
* : fixes issue with arbitrum block number
* : does an early return in case of stale report instead of revert
* - KeeperRegistry 2.0.1: implements workaround for buggy migrate function in 1.X
* - KeeperRegistry 2.0.0: implement OCR interface
* - KeeperRegistry 1.3.0: split contract into Proxy and Logic
Expand All @@ -50,11 +53,12 @@ contract KeeperRegistry2_1 is
* - KeeperRegistry 1.1.0: added flatFeeMicroLink
* - KeeperRegistry 1.0.0: initial release
*/
string public constant override typeAndVersion = "KeeperRegistry 2.0.1";
string public constant override typeAndVersion = "KeeperRegistry 2.1.0";

/**
* @inheritdoc MigratableKeeperRegistryInterface
*/

UpkeepFormat public constant override upkeepTranscoderVersion = UPKEEP_TRANSCODER_VERSION_BASE;

/**
Expand All @@ -67,7 +71,7 @@ contract KeeperRegistry2_1 is
*/
constructor(KeeperRegistryBase2_1 keeperRegistryLogic)
KeeperRegistryBase2_1(
keeperRegistryLogic.getPaymentModel(),
keeperRegistryLogic.getMode(),
keeperRegistryLogic.getLinkAddress(),
keeperRegistryLogic.getLinkNativeFeedAddress(),
keeperRegistryLogic.getFastGasFeedAddress()
Expand Down Expand Up @@ -140,7 +144,9 @@ contract KeeperRegistry2_1 is
}
}
// No upkeeps to be performed in this report
if (numUpkeepsPassedChecks == 0) revert StaleReport();
if (numUpkeepsPassedChecks == 0) {
return;
}

// Verify signatures
if (s_latestConfigDigest != reportContext[0]) revert ConfigDigestMismatch();
Expand All @@ -151,7 +157,7 @@ contract KeeperRegistry2_1 is
for (uint256 i = 0; i < report.upkeepIds.length; i++) {
if (upkeepTransmitInfo[i].earlyChecksPassed) {
// Check if this upkeep was already performed in this report
if (s_upkeep[report.upkeepIds[i]].lastPerformBlockNumber == uint32(block.number)) {
if (s_upkeep[report.upkeepIds[i]].lastPerformBlockNumber == uint32(_blockNum())) {
revert InvalidReport();
}

Expand All @@ -165,7 +171,7 @@ contract KeeperRegistry2_1 is
gasOverhead -= upkeepTransmitInfo[i].gasUsed;

// Store last perform block number for upkeep
s_upkeep[report.upkeepIds[i]].lastPerformBlockNumber = uint32(block.number);
s_upkeep[report.upkeepIds[i]].lastPerformBlockNumber = uint32(_blockNum());
}
}

Expand Down Expand Up @@ -358,7 +364,7 @@ contract KeeperRegistry2_1 is
s_fallbackLinkPrice = onchainConfigStruct.fallbackLinkPrice;

uint32 previousConfigBlockNumber = s_storage.latestConfigBlockNumber;
s_storage.latestConfigBlockNumber = uint32(block.number);
s_storage.latestConfigBlockNumber = uint32(_blockNum());
s_storage.configCount += 1;

s_latestConfigDigest = _configDigestFromConfigData(
Expand Down Expand Up @@ -413,14 +419,14 @@ contract KeeperRegistry2_1 is
/**
* @notice retrieve active upkeep IDs. Active upkeep is defined as an upkeep which is not paused and not canceled.
* @param startIndex starting index in list
* @param maxCount max number of upkeep IDs to retrieve (0 = unlimited)
* @param maxCount max count to retrieve (0 = unlimited)
* @dev the order of IDs in the list is **not guaranteed**, therefore, if making successive calls, one
* should consider keeping the blockheight constant to ensure a holistic picture of the contract state
*/
function getActiveUpkeepIDs(uint256 startIndex, uint256 maxCount) external view override returns (uint256[] memory) {
uint256 maxIdx = s_upkeepIDs.length();
if (startIndex >= maxIdx) revert IndexOutOfRange();
if (maxCount == 0 || maxCount + startIndex > maxIdx) {
if (maxCount == 0) {
maxCount = maxIdx - startIndex;
}
uint256[] memory ids = new uint256[](maxCount);
Expand Down Expand Up @@ -655,15 +661,15 @@ contract KeeperRegistry2_1 is
return false;
}

if (blockhash(wrappedPerformData.checkBlockNumber) != wrappedPerformData.checkBlockhash) {
if (_blockHash(wrappedPerformData.checkBlockNumber) != wrappedPerformData.checkBlockhash) {
// Can happen when the block on which report was generated got reorged
// We will also revert if checkBlockNumber is older than 256 blocks. In this case we rely on a new transmission
// with the latest checkBlockNumber
emit ReorgedUpkeepReport(upkeepId);
return false;
}

if (upkeep.maxValidBlocknumber <= block.number) {
if (upkeep.maxValidBlocknumber <= _blockNum()) {
// Can happen when an upkeep got cancelled after report was generated.
// However we have a CANCELLATION_DELAY of 50 blocks so shouldn't happen in practice
emit CancelledUpkeepReport(upkeepId);
Expand Down
51 changes: 40 additions & 11 deletions contracts/src/v0.8/dev/automation/2_1/KeeperRegistryBase2_1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/Enu
import "../../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol";
import "../../../vendor/@eth-optimism/contracts/0.8.6/contracts/L2/predeploys/OVM_GasPriceOracle.sol";
import "../../../automation/ExecutionPrevention.sol";
import {ArbSys} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol";
import {OnchainConfig, State, UpkeepFailureReason} from "../../interfaces/automation/2_1/AutomationRegistryInterface2_1.sol";
import "../../../ConfirmedOwner.sol";
import "../../../interfaces/AggregatorV3Interface.sol";
Expand Down Expand Up @@ -62,7 +63,7 @@ abstract contract KeeperRegistryBase2_1 is ConfirmedOwner, ExecutionPrevention {
bytes internal constant L1_FEE_DATA_PADDING =
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";

uint256 internal constant REGISTRY_GAS_OVERHEAD = 65_000; // Used only in maxPayment estimation, not in actual payment
uint256 internal constant REGISTRY_GAS_OVERHEAD = 70_000; // Used only in maxPayment estimation, not in actual payment
uint256 internal constant REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD = 20; // Used only in maxPayment estimation, not in actual payment. Value scales with performData length.
uint256 internal constant REGISTRY_PER_SIGNER_GAS_OVERHEAD = 7_500; // Used only in maxPayment estimation, not in actual payment. Value scales with f.

Expand All @@ -72,11 +73,12 @@ abstract contract KeeperRegistryBase2_1 is ConfirmedOwner, ExecutionPrevention {

OVM_GasPriceOracle internal constant OPTIMISM_ORACLE = OVM_GasPriceOracle(0x420000000000000000000000000000000000000F);
ArbGasInfo internal constant ARB_NITRO_ORACLE = ArbGasInfo(0x000000000000000000000000000000000000006C);
ArbSys internal constant ARB_SYS = ArbSys(0x0000000000000000000000000000000000000064);

LinkTokenInterface internal immutable i_link;
AggregatorV3Interface internal immutable i_linkNativeFeed;
AggregatorV3Interface internal immutable i_fastGasFeed;
PaymentModel internal immutable i_paymentModel;
Mode internal immutable i_mode;

// @dev - The storage is gas optimised for one and only function - transmit. All the storage accessed in transmit
// is stored compactly. Rest of the storage layout is not of much concern as transmit is the only hot path
Expand Down Expand Up @@ -136,7 +138,6 @@ abstract contract KeeperRegistryBase2_1 is ConfirmedOwner, ExecutionPrevention {
error IncorrectNumberOfSignatures();
error OnlyActiveSigners();
error DuplicateSigners();
error StaleReport();
error TooManyOracles();
error IncorrectNumberOfSigners();
error IncorrectNumberOfFaultyOracles();
Expand All @@ -158,7 +159,7 @@ abstract contract KeeperRegistryBase2_1 is ConfirmedOwner, ExecutionPrevention {
BIDIRECTIONAL
}

enum PaymentModel {
enum Mode {
DEFAULT,
ARBITRUM,
OPTIMISM
Expand Down Expand Up @@ -259,18 +260,18 @@ abstract contract KeeperRegistryBase2_1 is ConfirmedOwner, ExecutionPrevention {
event Unpaused(address account);

/**
* @param paymentModel the payment model of default, Arbitrum, or Optimism
* @param mode the contract mode of default, Arbitrum, or Optimism
* @param link address of the LINK Token
* @param linkNativeFeed address of the LINK/Native price feed
* @param fastGasFeed address of the Fast Gas price feed
*/
constructor(
PaymentModel paymentModel,
Mode mode,
address link,
address linkNativeFeed,
address fastGasFeed
) ConfirmedOwner(msg.sender) {
i_paymentModel = paymentModel;
i_mode = mode;
i_link = LinkTokenInterface(link);
i_linkNativeFeed = AggregatorV3Interface(linkNativeFeed);
i_fastGasFeed = AggregatorV3Interface(fastGasFeed);
Expand All @@ -280,8 +281,8 @@ abstract contract KeeperRegistryBase2_1 is ConfirmedOwner, ExecutionPrevention {
// GETTERS
////////

function getPaymentModel() external view returns (PaymentModel) {
return i_paymentModel;
function getMode() external view returns (Mode) {
return i_mode;
}

function getLinkAddress() external view returns (address) {
Expand Down Expand Up @@ -355,7 +356,7 @@ abstract contract KeeperRegistryBase2_1 is ConfirmedOwner, ExecutionPrevention {
}

uint256 l1CostWei = 0;
if (i_paymentModel == PaymentModel.OPTIMISM) {
if (i_mode == Mode.OPTIMISM) {
bytes memory txCallData = new bytes(0);
if (isExecution) {
txCallData = bytes.concat(msg.data, L1_FEE_DATA_PADDING);
Expand All @@ -366,7 +367,7 @@ abstract contract KeeperRegistryBase2_1 is ConfirmedOwner, ExecutionPrevention {
txCallData = new bytes(4 * s_storage.maxPerformDataSize);
}
l1CostWei = OPTIMISM_ORACLE.getL1Fee(txCallData);
} else if (i_paymentModel == PaymentModel.ARBITRUM) {
} else if (i_mode == Mode.ARBITRUM) {
l1CostWei = ARB_NITRO_ORACLE.getCurrentTxL1GasFees();
}
// if it's not performing upkeeps, use gas ceiling multiplier to estimate the upper bound
Expand Down Expand Up @@ -444,6 +445,34 @@ abstract contract KeeperRegistryBase2_1 is ConfirmedOwner, ExecutionPrevention {
return transmitter.balance;
}

/**
* @notice returns the current block number in a chain agnostic manner
*/
function _blockNum() internal view returns (uint256) {
if (i_mode == Mode.ARBITRUM) {
return ARB_SYS.arbBlockNumber();
} else {
return block.number;
}
}

/**
* @notice returns the blockhash of the provided block number in a chain agnostic manner
* @param n the blocknumber to retrieve the blockhash for
* @return blockhash the blockhash of block number n, or 0 if n is out queryable of range
*/
function _blockHash(uint256 n) internal view returns (bytes32) {
if (i_mode == Mode.ARBITRUM) {
uint256 blockNum = ARB_SYS.arbBlockNumber();
if (n >= blockNum || blockNum - n > 256) {
return "";
}
return ARB_SYS.arbBlockHash(n);
} else {
return blockhash(n);
}
}

/**
* @notice replicates Open Zeppelin's ReentrancyGuard but optimized to fit our storage
*/
Expand Down
Loading

0 comments on commit b8279a5

Please sign in to comment.