Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

initial design for automation chain expansion and FG/LN feeds removal #11139

Closed
wants to merge 11 commits into from
8 changes: 4 additions & 4 deletions contracts/src/v0.8/automation/v2_1/KeeperRegistry2_1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,12 @@ contract KeeperRegistry2_1 is KeeperRegistryBase2_1, OCR2Abstract, Chainable, IE
upkeepTransmitInfo[i].triggerType = _getTriggerType(report.upkeepIds[i]);
upkeepTransmitInfo[i].maxLinkPayment = _getMaxLinkPayment(
hotVars,
report.cfgs[i],
upkeepTransmitInfo[i].triggerType,
uint32(report.gasLimits[i]),
uint32(report.performDatas[i].length),
report.fastGasWei,
report.linkNative,
// report.fastGasWei,
// report.linkNative,
true
);
(upkeepTransmitInfo[i].earlyChecksPassed, upkeepTransmitInfo[i].dedupID) = _prePerformChecks(
Expand Down Expand Up @@ -152,10 +153,9 @@ contract KeeperRegistry2_1 is KeeperRegistryBase2_1, OCR2Abstract, Chainable, IE

(reimbursement, premium) = _postPerformPayment(
hotVars,
report.cfgs[i],
report.upkeepIds[i],
upkeepTransmitInfo[i],
report.fastGasWei,
report.linkNative,
numUpkeepsPassedChecks
);
totalPremium += premium;
Expand Down
106 changes: 43 additions & 63 deletions contracts/src/v0.8/automation/v2_1/KeeperRegistryBase2_1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -341,8 +341,7 @@ abstract contract KeeperRegistryBase2_1 is ConfirmedOwner, ExecutionPrevention {

/// @dev Report transmitted by OCR to transmit function
struct Report {
uint256 fastGasWei;
uint256 linkNative;
ChainConfig[] cfgs;
uint256[] upkeepIds;
uint256[] gasLimits;
bytes[] triggers;
Expand Down Expand Up @@ -405,6 +404,13 @@ abstract contract KeeperRegistryBase2_1 is ConfirmedOwner, ExecutionPrevention {
bytes32 blockHash;
}

struct ChainConfig {
uint256 fastGas;
uint256 linkNative;
uint256 executionL1GasCost;
uint256 estimatedL1GasCost;
}

event AdminPrivilegeConfigSet(address indexed admin, bytes privilegeConfig);
event CancelledUpkeepReport(uint256 indexed id, bytes trigger);
event DedupKeyAdded(bytes32 indexed dedupKey);
Expand Down Expand Up @@ -527,86 +533,64 @@ abstract contract KeeperRegistryBase2_1 is ConfirmedOwner, ExecutionPrevention {
* for gas it takes the min of gas price in the transaction or the fast gas
* price in order to reduce costs for the upkeep clients.
*/
function _getFeedData(HotVars memory hotVars) internal view returns (uint256 gasWei, uint256 linkNative) {
uint32 stalenessSeconds = hotVars.stalenessSeconds;
bool staleFallback = stalenessSeconds > 0;
uint256 timestamp;
int256 feedValue;
(, feedValue, , timestamp, ) = i_fastGasFeed.latestRoundData();
if (
feedValue <= 0 || block.timestamp < timestamp || (staleFallback && stalenessSeconds < block.timestamp - timestamp)
) {
gasWei = s_fallbackGasPrice;
} else {
gasWei = uint256(feedValue);
}
(, feedValue, , timestamp, ) = i_linkNativeFeed.latestRoundData();
if (
feedValue <= 0 || block.timestamp < timestamp || (staleFallback && stalenessSeconds < block.timestamp - timestamp)
) {
linkNative = s_fallbackLinkPrice;
} else {
linkNative = uint256(feedValue);
}
return (gasWei, linkNative);
}
// function _getFeedData(HotVars memory hotVars) internal view returns (uint256 gasWei, uint256 linkNative) {
// uint32 stalenessSeconds = hotVars.stalenessSeconds;
// bool staleFallback = stalenessSeconds > 0;
// uint256 timestamp;
// int256 feedValue;
// (, feedValue, , timestamp, ) = i_fastGasFeed.latestRoundData();
// if (
// feedValue <= 0 || block.timestamp < timestamp || (staleFallback && stalenessSeconds < block.timestamp - timestamp)
// ) {
// gasWei = s_fallbackGasPrice;
// } else {
// gasWei = uint256(feedValue);
// }
// (, feedValue, , timestamp, ) = i_linkNativeFeed.latestRoundData();
// if (
// feedValue <= 0 || block.timestamp < timestamp || (staleFallback && stalenessSeconds < block.timestamp - timestamp)
// ) {
// linkNative = s_fallbackLinkPrice;
// } else {
// linkNative = uint256(feedValue);
// }
// return (gasWei, linkNative);
// }

/**
* @dev calculates LINK paid for gas spent plus a configure premium percentage
* @param gasLimit the amount of gas used
* @param gasOverhead the amount of gas overhead
* @param fastGasWei the fast gas price
* @param linkNative the exchange ratio between LINK and Native token
* @param numBatchedUpkeeps the number of upkeeps in this batch. Used to divide the L1 cost
* @param isExecution if this is triggered by a perform upkeep function
*/
function _calculatePaymentAmount(
HotVars memory hotVars,
ChainConfig memory cfg,
uint256 gasLimit,
uint256 gasOverhead,
uint256 fastGasWei,
uint256 linkNative,
uint16 numBatchedUpkeeps,
bool isExecution
) internal view returns (uint96, uint96) {
uint256 gasWei = fastGasWei * hotVars.gasCeilingMultiplier;
uint256 gasWei = cfg.fastGas * hotVars.gasCeilingMultiplier;
// in case it's actual execution use actual gas price, capped by fastGasWei * gasCeilingMultiplier
if (isExecution && tx.gasprice < gasWei) {
gasWei = tx.gasprice;
}

uint256 l1CostWei = 0;
if (i_mode == Mode.OPTIMISM) {
bytes memory txCallData = new bytes(0);
if (isExecution) {
txCallData = bytes.concat(msg.data, L1_FEE_DATA_PADDING);
} else {
// fee is 4 per 0 byte, 16 per non-zero byte. Worst case we can have
// s_storage.maxPerformDataSize non zero-bytes. Instead of setting bytes to non-zero
// we initialize 'new bytes' of length 4*maxPerformDataSize to cover for zero bytes.
txCallData = new bytes(4 * s_storage.maxPerformDataSize);
}
l1CostWei = OPTIMISM_ORACLE.getL1Fee(txCallData);
} else if (i_mode == Mode.ARBITRUM) {
if (isExecution) {
l1CostWei = ARB_NITRO_ORACLE.getCurrentTxL1GasFees();
} else {
// fee is 4 per 0 byte, 16 per non-zero byte - we assume all non-zero and
// max data size to calculate max payment
(, uint256 perL1CalldataUnit, , , , ) = ARB_NITRO_ORACLE.getPricesInWei();
l1CostWei = perL1CalldataUnit * s_storage.maxPerformDataSize * 16;
}
}
uint256 l1CostWei;
// if it's not performing upkeeps, use gas ceiling multiplier to estimate the upper bound
if (!isExecution) {
l1CostWei = hotVars.gasCeilingMultiplier * l1CostWei;
l1CostWei = hotVars.gasCeilingMultiplier * cfg.estimatedL1GasCost;
} else {
l1CostWei = cfg.executionL1GasCost;
}
// Divide l1CostWei among all batched upkeeps. Spare change from division is not charged
l1CostWei = l1CostWei / numBatchedUpkeeps;

uint256 gasPayment = ((gasWei * (gasLimit + gasOverhead) + l1CostWei) * 1e18) / linkNative;
uint256 gasPayment = ((gasWei * (gasLimit + gasOverhead) + l1CostWei) * 1e18) / cfg.linkNative;
uint256 premium = (((gasWei * gasLimit) + l1CostWei) * 1e9 * hotVars.paymentPremiumPPB) /
linkNative +
cfg.linkNative +
uint256(hotVars.flatFeeMicroLink) *
1e12;
// LINK_TOTAL_SUPPLY < UINT96_MAX
Expand All @@ -619,20 +603,18 @@ abstract contract KeeperRegistryBase2_1 is ConfirmedOwner, ExecutionPrevention {
*/
function _getMaxLinkPayment(
HotVars memory hotVars,
ChainConfig memory cfg,
Trigger triggerType,
uint32 performGas,
uint32 performDataLength,
uint256 fastGasWei,
uint256 linkNative,
bool isExecution // Whether this is an actual perform execution or just a simulation
) internal view returns (uint96) {
uint256 gasOverhead = _getMaxGasOverhead(triggerType, performDataLength, hotVars.f);
(uint96 reimbursement, uint96 premium) = _calculatePaymentAmount(
hotVars,
cfg,
performGas,
gasOverhead,
fastGasWei,
linkNative,
1, // Consider only 1 upkeep in batch to get maxPayment
isExecution
);
Expand Down Expand Up @@ -871,18 +853,16 @@ abstract contract KeeperRegistryBase2_1 is ConfirmedOwner, ExecutionPrevention {
*/
function _postPerformPayment(
HotVars memory hotVars,
ChainConfig memory cfg,
uint256 upkeepId,
UpkeepTransmitInfo memory upkeepTransmitInfo,
uint256 fastGasWei,
uint256 linkNative,
uint16 numBatchedUpkeeps
) internal returns (uint96 gasReimbursement, uint96 premium) {
(gasReimbursement, premium) = _calculatePaymentAmount(
hotVars,
cfg,
upkeepTransmitInfo.gasUsed,
upkeepTransmitInfo.gasOverhead,
fastGasWei,
linkNative,
numBatchedUpkeeps,
true
);
Expand Down
54 changes: 29 additions & 25 deletions contracts/src/v0.8/automation/v2_1/KeeperRegistryLogicA2_1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ contract KeeperRegistryLogicA2_1 is KeeperRegistryBase2_1, Chainable {
*/
function checkUpkeep(
uint256 id,
bytes memory triggerData
bytes memory triggerData,
ChainConfig memory cfg
)
public
cannotExecute
Expand All @@ -55,9 +56,10 @@ contract KeeperRegistryLogicA2_1 is KeeperRegistryBase2_1, Chainable {
bytes memory performData,
UpkeepFailureReason upkeepFailureReason,
uint256 gasUsed,
uint256 gasLimit,
uint256 fastGasWei,
uint256 linkNative
uint256 gasLimit//,
// likely these 2 values don't need to be returned anymore. otherwise, we can just pass the values from chain config here.
// uint256 fastGasWei,
// uint256 linkNative
)
{
Trigger triggerType = _getTriggerType(id);
Expand All @@ -69,14 +71,15 @@ contract KeeperRegistryLogicA2_1 is KeeperRegistryBase2_1, Chainable {
return (false, bytes(""), UpkeepFailureReason.UPKEEP_CANCELLED, 0, upkeep.performGas, 0, 0);
if (upkeep.paused) return (false, bytes(""), UpkeepFailureReason.UPKEEP_PAUSED, 0, upkeep.performGas, 0, 0);

(fastGasWei, linkNative) = _getFeedData(hotVars);
// (fastGasWei, linkNative) = _getFeedData(hotVars);
uint96 maxLinkPayment = _getMaxLinkPayment(
hotVars,
cfg,
triggerType,
upkeep.performGas,
s_storage.maxPerformDataSize,
fastGasWei,
linkNative,
//fastGasWei,
//linkNative,
false
);
if (upkeep.balance < maxLinkPayment) {
Expand All @@ -97,19 +100,19 @@ contract KeeperRegistryLogicA2_1 is KeeperRegistryBase2_1, Chainable {
bytes(""),
UpkeepFailureReason.REVERT_DATA_EXCEEDS_LIMIT,
gasUsed,
upkeep.performGas,
fastGasWei,
linkNative
upkeep.performGas//,
//fastGasWei,
//linkNative
);
}
return (
upkeepNeeded,
result,
UpkeepFailureReason.TARGET_CHECK_REVERTED,
gasUsed,
upkeep.performGas,
fastGasWei,
linkNative
upkeep.performGas//,
//fastGasWei,
//linkNative
);
}

Expand All @@ -120,9 +123,9 @@ contract KeeperRegistryLogicA2_1 is KeeperRegistryBase2_1, Chainable {
bytes(""),
UpkeepFailureReason.UPKEEP_NOT_NEEDED,
gasUsed,
upkeep.performGas,
fastGasWei,
linkNative
upkeep.performGas//,
//fastGasWei,
//linkNative
);

if (performData.length > s_storage.maxPerformDataSize)
Expand All @@ -131,33 +134,34 @@ contract KeeperRegistryLogicA2_1 is KeeperRegistryBase2_1, Chainable {
bytes(""),
UpkeepFailureReason.PERFORM_DATA_EXCEEDS_LIMIT,
gasUsed,
upkeep.performGas,
fastGasWei,
linkNative
upkeep.performGas//,
//fastGasWei,
//linkNative
);

return (upkeepNeeded, performData, upkeepFailureReason, gasUsed, upkeep.performGas, fastGasWei, linkNative);
return (upkeepNeeded, performData, upkeepFailureReason, gasUsed, upkeep.performGas/*, fastGasWei, linkNative*/);
}

/**
* @notice see other checkUpkeep function for description
* @dev this function may be deprecated in a future version of chainlink automation
*/
function checkUpkeep(
uint256 id
uint256 id,
ChainConfig memory cfg
)
external
returns (
bool upkeepNeeded,
bytes memory performData,
UpkeepFailureReason upkeepFailureReason,
uint256 gasUsed,
uint256 gasLimit,
uint256 fastGasWei,
uint256 linkNative
uint256 gasLimit//,
//uint256 fastGasWei,
//uint256 linkNative
)
{
return checkUpkeep(id, bytes(""));
return checkUpkeep(id, bytes(""), cfg);
}

/**
Expand Down
12 changes: 6 additions & 6 deletions contracts/src/v0.8/automation/v2_1/KeeperRegistryLogicB2_1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -455,28 +455,28 @@ contract KeeperRegistryLogicB2_1 is KeeperRegistryBase2_1 {
* @notice calculates the minimum balance required for an upkeep to remain eligible
* @param id the upkeep id to calculate minimum balance for
*/
function getMinBalance(uint256 id) external view returns (uint96) {
return getMinBalanceForUpkeep(id);
function getMinBalance(uint256 id, ChainConfig memory cfg) external view returns (uint96) {
return getMinBalanceForUpkeep(id, cfg);
}

/**
* @notice calculates the minimum balance required for an upkeep to remain eligible
* @param id the upkeep id to calculate minimum balance for
* @dev this will be deprecated in a future version in favor of getMinBalance
*/
function getMinBalanceForUpkeep(uint256 id) public view returns (uint96 minBalance) {
return getMaxPaymentForGas(_getTriggerType(id), s_upkeep[id].performGas);
function getMinBalanceForUpkeep(uint256 id, ChainConfig memory cfg) public view returns (uint96 minBalance) {
return getMaxPaymentForGas(_getTriggerType(id), cfg, s_upkeep[id].performGas);
}

/**
* @notice calculates the maximum payment for a given gas limit
* @param gasLimit the gas to calculate payment for
*/
function getMaxPaymentForGas(Trigger triggerType, uint32 gasLimit) public view returns (uint96 maxPayment) {
function getMaxPaymentForGas(Trigger triggerType, ChainConfig memory cfg, uint32 gasLimit) public view returns (uint96 maxPayment) {
HotVars memory hotVars = s_hotVars;
(uint256 fastGasWei, uint256 linkNative) = _getFeedData(hotVars);
return
_getMaxLinkPayment(hotVars, triggerType, gasLimit, s_storage.maxPerformDataSize, fastGasWei, linkNative, false);
_getMaxLinkPayment(hotVars, cfg, triggerType, gasLimit, s_storage.maxPerformDataSize, false);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ func (e reportEncoder) Encode(results ...ocr2keepers.CheckResult) ([]byte, error
}

report := automation_utils_2_1.KeeperRegistryBase21Report{
FastGasWei: big.NewInt(0),
LinkNative: big.NewInt(0),
FastGasWei: big.NewInt(0),
LinkNative: big.NewInt(0),
// Cfgs: make([]ChainConfig, len(results)),
UpkeepIds: make([]*big.Int, len(results)),
GasLimits: make([]*big.Int, len(results)),
Triggers: make([][]byte, len(results)),
Expand All @@ -55,7 +56,7 @@ func (e reportEncoder) Encode(results ...ocr2keepers.CheckResult) ([]byte, error
report.LinkNative = result.LinkNative
}
}

// report.Cfgs[i] = ChainConfig(result.l1GasCost, result.fastGas, result.linkNative)
id := result.UpkeepID.BigInt()
report.UpkeepIds[i] = id
report.GasLimits[i] = big.NewInt(0).SetUint64(result.GasAllocated)
Expand Down
Loading
Loading