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

add UpkeepCharged event #13096

Merged
merged 1 commit into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/sharp-walls-poke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"chainlink": patch
---

add upkeepCharged event #bugfix
5 changes: 5 additions & 0 deletions contracts/.changeset/fresh-rivers-think.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@chainlink/contracts": patch
---

add upkeepCharged event #bugfix

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@ import {AutomationRegistryBase2_3} from "./AutomationRegistryBase2_3.sol";
import {AutomationRegistryLogicA2_3} from "./AutomationRegistryLogicA2_3.sol";
import {AutomationRegistryLogicC2_3} from "./AutomationRegistryLogicC2_3.sol";
import {Chainable} from "../../Chainable.sol";
import {IERC677Receiver} from "../../../shared/interfaces/IERC677Receiver.sol";
import {OCR2Abstract} from "../../../shared/ocr2/OCR2Abstract.sol";
import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol";

/**
* @notice Registry for adding work for Chainlink nodes to perform on client
* contracts. Clients must support the AutomationCompatibleInterface interface.
*/
contract AutomationRegistry2_3 is AutomationRegistryBase2_3, OCR2Abstract, Chainable, IERC677Receiver {
contract AutomationRegistry2_3 is AutomationRegistryBase2_3, OCR2Abstract, Chainable {
using Address for address;
using EnumerableSet for EnumerableSet.UintSet;
using EnumerableSet for EnumerableSet.AddressSet;
Expand Down Expand Up @@ -213,7 +212,7 @@ contract AutomationRegistry2_3 is AutomationRegistryBase2_3, OCR2Abstract, Chain
emit UpkeepPerformed(
report.upkeepIds[i],
upkeepTransmitInfo[i].performSuccess,
receipt.gasReimbursementInJuels + receipt.premiumInJuels, // TODO - this is currently the LINK amount, but may change to billing token
receipt.gasChargeInBillingToken + receipt.premiumInBillingToken,
upkeepTransmitInfo[i].gasUsed,
gasOverhead,
report.triggers[i]
Expand All @@ -227,23 +226,6 @@ contract AutomationRegistry2_3 is AutomationRegistryBase2_3, OCR2Abstract, Chain
s_reserveAmounts[IERC20(address(i_link))] += transmitVars.totalReimbursement + transmitVars.totalPremium;
}

/**
* @notice uses LINK's transferAndCall to LINK and add funding to an upkeep
* @dev safe to cast uint256 to uint96 as total LINK supply is under UINT96MAX
* @param sender the account which transferred the funds
* @param amount number of LINK transfer
*/
function onTokenTransfer(address sender, uint256 amount, bytes calldata data) external override {
if (msg.sender != address(i_link)) revert OnlyCallableByLINKToken();
if (data.length != 32) revert InvalidDataLength();
uint256 id = abi.decode(data, (uint256));
if (s_upkeep[id].maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled();
if (address(s_upkeep[id].billingToken) != address(i_link)) revert InvalidToken();
s_upkeep[id].balance = s_upkeep[id].balance + uint96(amount);
s_reserveAmounts[IERC20(address(i_link))] = s_reserveAmounts[IERC20(address(i_link))] + amount;
emit FundsAdded(id, sender, uint96(amount));
}

// ================================================================
// | OCR2ABSTRACT |
// ================================================================
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner {
// Next block of constants are only used in maxPayment estimation during checkUpkeep simulation
// These values are calibrated using hardhat tests which simulate various cases and verify that
// the variables result in accurate estimation
uint256 internal constant REGISTRY_CONDITIONAL_OVERHEAD = 93_000; // Fixed gas overhead for conditional upkeeps
uint256 internal constant REGISTRY_LOG_OVERHEAD = 118_000; // Fixed gas overhead for log upkeeps
uint256 internal constant REGISTRY_CONDITIONAL_OVERHEAD = 97_700; // Fixed gas overhead for conditional upkeeps
uint256 internal constant REGISTRY_LOG_OVERHEAD = 122_000; // Fixed gas overhead for log upkeeps
uint256 internal constant REGISTRY_PER_SIGNER_GAS_OVERHEAD = 5_600; // Value scales with f
uint256 internal constant REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD = 24; // Per perform data byte overhead

Expand All @@ -59,7 +59,7 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner {
// to account for gas used in payment processing. These values are calibrated using hardhat tests which simulates various cases and verifies that
// the variables result in accurate estimation
uint256 internal constant ACCOUNTING_FIXED_GAS_OVERHEAD = 51_200; // Fixed overhead per tx
uint256 internal constant ACCOUNTING_PER_UPKEEP_GAS_OVERHEAD = 9_200; // Overhead per upkeep performed in batch
uint256 internal constant ACCOUNTING_PER_UPKEEP_GAS_OVERHEAD = 13_200; // Overhead per upkeep performed in batch

LinkTokenInterface internal immutable i_link;
AggregatorV3Interface internal immutable i_linkUSDFeed;
Expand Down Expand Up @@ -441,8 +441,16 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner {
struct PaymentReceipt {
uint96 gasChargeInBillingToken;
uint96 premiumInBillingToken;
// one word ends
uint96 gasReimbursementInJuels;
uint96 premiumInJuels;
// second word ends
IERC20 billingToken;
uint96 linkUSD;
// third word ends
uint96 nativeUSD;
uint96 billingUSD;
// fourth word ends
}

event AdminPrivilegeConfigSet(address indexed admin, bytes privilegeConfig);
Expand Down Expand Up @@ -480,6 +488,7 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner {
uint256 gasOverhead,
bytes trigger
);
event UpkeepCharged(uint256 indexed id, PaymentReceipt receipt);
event UpkeepPrivilegeConfigSet(uint256 indexed id, bytes privilegeConfig);
event UpkeepReceived(uint256 indexed id, uint256 startingBalance, address importedFrom);
event UpkeepRegistered(uint256 indexed id, uint32 performGas, address admin);
Expand Down Expand Up @@ -655,11 +664,11 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner {
}

/**
* @dev calculates LINK paid for gas spent plus a configure premium percentage
* @param hotVars the hot path variables
* @param paymentParams the pricing data and gas usage data
* @return receipt the receipt of payment with pricing breakdown
* @dev use of PaymentParams struct is necessary to avoid stack too deep errors
* @dev calculates LINK paid for gas spent plus a configure premium percentage
* @dev 1 USD = 1e18 attoUSD
* @dev 1 USD = 1e26 hexaicosaUSD (had to borrow this prefix from geometry because there is no metric prefix for 1e-26)
* @dev 1 millicent = 1e-5 USD = 1e13 attoUSD
Expand Down Expand Up @@ -702,6 +711,11 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner {
);
receipt.premiumInJuels = SafeCast.toUint96(premiumHexaicosaUSD / paymentParams.linkUSD);

receipt.billingToken = paymentParams.billingToken;
receipt.linkUSD = SafeCast.toUint96(paymentParams.linkUSD);
receipt.nativeUSD = SafeCast.toUint96(paymentParams.nativeUSD);
receipt.billingUSD = SafeCast.toUint96(paymentParams.billingTokenParams.priceUSD);
Comment on lines +715 to +717
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is uint96 definitely big enough to hold these? based on the struct, we could make these uint128 with no additional storage requirements

Copy link
Contributor Author

@shileiwill shileiwill May 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think uint96 should be enough:
The max number we can hold with uint96 is approximately 10^27.
For the 3 rates, we require the the Feed to be 8 decimals. So the ratio can be as big as 10^19 for Native, LINK and Billing Token.

Increasing from uint96 to uint128 seems to require one more word since we added (IERC20:160 bits, linkUSD: 128/96 bits, nativeUSD 128/96 bits and billingUSD 128/96 bits)
Let me know if the above makes sense. Not a strong opinion, happy to update~

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SGTM 👍


return receipt;
}

Expand Down Expand Up @@ -1026,6 +1040,7 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner {
s_upkeep[upkeepId].amountSpent += payment;
s_reserveAmounts[paymentParams.billingToken] -= payment;

emit UpkeepCharged(upkeepId, receipt);
return receipt;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ import {UpkeepTranscoderInterfaceV2} from "../../interfaces/UpkeepTranscoderInte
import {MigratableKeeperRegistryInterfaceV2} from "../../interfaces/MigratableKeeperRegistryInterfaceV2.sol";
import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {SafeERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol";
import {IERC677Receiver} from "../../../shared/interfaces/IERC677Receiver.sol";

/**
* @notice Logic contract, works in tandem with AutomationRegistry as a proxy
*/
contract AutomationRegistryLogicA2_3 is AutomationRegistryBase2_3, Chainable {
contract AutomationRegistryLogicA2_3 is AutomationRegistryBase2_3, Chainable, IERC677Receiver {
using Address for address;
using EnumerableSet for EnumerableSet.UintSet;
using EnumerableSet for EnumerableSet.AddressSet;
Expand All @@ -43,6 +44,23 @@ contract AutomationRegistryLogicA2_3 is AutomationRegistryBase2_3, Chainable {
Chainable(address(logicB))
{}

/**
* @notice uses LINK's transferAndCall to LINK and add funding to an upkeep
* @dev safe to cast uint256 to uint96 as total LINK supply is under UINT96MAX
* @param sender the account which transferred the funds
* @param amount number of LINK transfer
*/
function onTokenTransfer(address sender, uint256 amount, bytes calldata data) external override {
if (msg.sender != address(i_link)) revert OnlyCallableByLINKToken();
if (data.length != 32) revert InvalidDataLength();
uint256 id = abi.decode(data, (uint256));
if (s_upkeep[id].maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled();
if (address(s_upkeep[id].billingToken) != address(i_link)) revert InvalidToken();
s_upkeep[id].balance = s_upkeep[id].balance + uint96(amount);
s_reserveAmounts[IERC20(address(i_link))] = s_reserveAmounts[IERC20(address(i_link))] + amount;
emit FundsAdded(id, sender, uint96(amount));
}

// ================================================================
// | UPKEEP MANAGEMENT |
// ================================================================
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ const emptyBytes = '0x'
const emptyBytes32 =
'0x0000000000000000000000000000000000000000000000000000000000000000'

const transmitGasOverhead = 1_000_000
const transmitGasOverhead = 1_025_000
const checkGasOverhead = 600_000

const stalenessSeconds = BigNumber.from(43820)
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ automation_forwarder_logic: ../../contracts/solc/v0.8.16/AutomationForwarderLogi
automation_registrar_wrapper2_1: ../../contracts/solc/v0.8.16/AutomationRegistrar2_1/AutomationRegistrar2_1.abi ../../contracts/solc/v0.8.16/AutomationRegistrar2_1/AutomationRegistrar2_1.bin eb06d853aab39d3196c593b03e555851cbe8386e0fe54a74c2479f62d14b3c42
automation_registrar_wrapper2_3: ../../contracts/solc/v0.8.19/AutomationRegistrar2_3/AutomationRegistrar2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistrar2_3/AutomationRegistrar2_3.bin 05dfc1601a6e8a43d98c982b5cb1ad1060b49948dc0c8ccd829ca2c9f6d9430e
automation_registry_logic_a_wrapper_2_2: ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_2/AutomationRegistryLogicA2_2.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_2/AutomationRegistryLogicA2_2.bin 2f267fb8467a15c587ce4586ac56069f7229344ad3936430d7c7624c0528a171
automation_registry_logic_a_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_3/AutomationRegistryLogicA2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_3/AutomationRegistryLogicA2_3.bin e8ae5a25765092049f79eb8344db8e572bacb43c6c6e284b3d00f82667c248f7
automation_registry_logic_a_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_3/AutomationRegistryLogicA2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_3/AutomationRegistryLogicA2_3.bin 73b5cc3ece642abbf6f2a4c9188335b71404f4dd0ad10b761390b6397af6f1c8
automation_registry_logic_b_wrapper_2_2: ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_2/AutomationRegistryLogicB2_2.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_2/AutomationRegistryLogicB2_2.bin a6d33dfbbfb0ff253eb59a51f4f6d6d4c22ea5ec95aae52d25d49a312b37a22f
automation_registry_logic_b_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_3/AutomationRegistryLogicB2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_3/AutomationRegistryLogicB2_3.bin f2bb8dc7fdb8b48ba0a0501e3c195676e73d0e56d94c9061edf12830ebbce495
automation_registry_logic_b_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_3/AutomationRegistryLogicB2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_3/AutomationRegistryLogicB2_3.bin acee8aca275f0aaeae781a505eacb59414bb685725a8af199c71a01f54739784
automation_registry_wrapper_2_2: ../../contracts/solc/v0.8.19/AutomationRegistry2_2/AutomationRegistry2_2.abi ../../contracts/solc/v0.8.19/AutomationRegistry2_2/AutomationRegistry2_2.bin de60f69878e9b32a291a001c91fc8636544c2cfbd9b507c8c1a4873b602bfb62
automation_registry_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistry2_3/AutomationRegistry2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistry2_3/AutomationRegistry2_3.bin fa9159b9dd36e37209d9805d0fde82f1cba7d0e2674ecc5a7595d48eb40203c4
automation_registry_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistry2_3/AutomationRegistry2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistry2_3/AutomationRegistry2_3.bin 6bab795655521b2fee8425b52f567b7a3f5d9e63b36b9a31f165af59636201c1
automation_utils_2_1: ../../contracts/solc/v0.8.16/AutomationUtils2_1/AutomationUtils2_1.abi ../../contracts/solc/v0.8.16/AutomationUtils2_1/AutomationUtils2_1.bin 815b17b63f15d26a0274b962eefad98cdee4ec897ead58688bbb8e2470e585f5
automation_utils_2_2: ../../contracts/solc/v0.8.19/AutomationUtils2_2/AutomationUtils2_2.abi ../../contracts/solc/v0.8.19/AutomationUtils2_2/AutomationUtils2_2.bin 8743f6231aaefa3f2a0b2d484258070d506e2d0860690e66890dccc3949edb2e
automation_utils_2_3: ../../contracts/solc/v0.8.19/AutomationUtils2_3/AutomationUtils2_3.abi ../../contracts/solc/v0.8.19/AutomationUtils2_3/AutomationUtils2_3.bin 11e2b481dc9a4d936e3443345d45d2cc571164459d214917b42a8054b295393b
Expand All @@ -31,7 +31,7 @@ dummy_protocol_wrapper: ../../contracts/solc/v0.8.16/DummyProtocol/DummyProtocol
gas_wrapper: ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.abi ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.bin 4a5dcdac486d18fcd58e3488c15c1710ae76b977556a3f3191bd269a4bc75723
gas_wrapper_mock: ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.abi ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.bin a9b08f18da59125c6fc305855710241f3d35161b8b9f3e3f635a7b1d5c6da9c8
i_automation_registry_master_wrapper_2_2: ../../contracts/solc/v0.8.19/IAutomationRegistryMaster/IAutomationRegistryMaster.abi ../../contracts/solc/v0.8.19/IAutomationRegistryMaster/IAutomationRegistryMaster.bin 9ff7087179f89f9b05964ebc3e71332fce11f1b8e85058f7b16b3bc0dd6fb96b
i_automation_registry_master_wrapper_2_3: ../../contracts/solc/v0.8.19/IAutomationRegistryMaster2_3/IAutomationRegistryMaster2_3.abi ../../contracts/solc/v0.8.19/IAutomationRegistryMaster2_3/IAutomationRegistryMaster2_3.bin aa65a3c4bc89fadae2f389da6643caad50e9b9948d61e2d40d8f00774f356a80
i_automation_registry_master_wrapper_2_3: ../../contracts/solc/v0.8.19/IAutomationRegistryMaster2_3/IAutomationRegistryMaster2_3.abi ../../contracts/solc/v0.8.19/IAutomationRegistryMaster2_3/IAutomationRegistryMaster2_3.bin d240ee2e5d66cc49dd11008ec405c97605d53e151b7c80b3518ffeb412845d19
i_automation_v21_plus_common: ../../contracts/solc/v0.8.19/IAutomationV21PlusCommon/IAutomationV21PlusCommon.abi ../../contracts/solc/v0.8.19/IAutomationV21PlusCommon/IAutomationV21PlusCommon.bin e8a601ec382c0a2e83c49759de13b0622b5e04e6b95901e96a1e9504329e594c
i_chain_module: ../../contracts/solc/v0.8.19/IChainModule/IChainModule.abi ../../contracts/solc/v0.8.19/IChainModule/IChainModule.bin 383611981c86c70522f41b8750719faacc7d7933a22849d5004799ebef3371fa
i_keeper_registry_master_wrapper_2_1: ../../contracts/solc/v0.8.16/IKeeperRegistryMaster/IKeeperRegistryMaster.abi ../../contracts/solc/v0.8.16/IKeeperRegistryMaster/IKeeperRegistryMaster.bin ee0f150b3afbab2df3d24ff3f4c87851efa635da30db04cd1f70cb4e185a1781
Expand Down
Loading