Skip to content

Commit

Permalink
Merge branch 'develop' into jtw/increase-instant-finality-depth
Browse files Browse the repository at this point in the history
  • Loading branch information
silaslenihan authored May 29, 2024
2 parents 272e5e3 + 8491b24 commit f3bbe6e
Show file tree
Hide file tree
Showing 9 changed files with 141 additions and 16 deletions.
5 changes: 5 additions & 0 deletions .changeset/plenty-waves-exercise.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"chainlink": patch
---

roundup #bugfix
5 changes: 5 additions & 0 deletions contracts/.changeset/nasty-tables-guess.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@chainlink/contracts": patch
---

roundup #bugfix
98 changes: 98 additions & 0 deletions contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -1665,6 +1665,104 @@ contract Transmit is SetUp {
"native reserve amount should have decreased"
);
}

function test_handlesInsufficientBalanceWithUSDToken18() external {
// deploy and configure a registry with ON_CHAIN payout
(Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN);

// register an upkeep and add funds
uint256 upkeepID = registry.registerUpkeep(
address(TARGET1),
1000000,
UPKEEP_ADMIN,
0,
address(usdToken18),
"",
"",
""
);
_mintERC20_18Decimals(UPKEEP_ADMIN, 1e20);
vm.startPrank(UPKEEP_ADMIN);
usdToken18.approve(address(registry), 1e20);
registry.addFunds(upkeepID, 1); // smaller than gasCharge
uint256 balance = registry.getBalance(upkeepID);

// manually create a transmit
vm.recordLogs();
_transmit(upkeepID, registry);
Vm.Log[] memory entries = vm.getRecordedLogs();

assertEq(entries.length, 3);
Vm.Log memory l1 = entries[1];
assertEq(
l1.topics[0],
keccak256("UpkeepCharged(uint256,(uint96,uint96,uint96,uint96,address,uint96,uint96,uint96))")
);
(
uint96 gasChargeInBillingToken,
uint96 premiumInBillingToken,
uint96 gasReimbursementInJuels,
uint96 premiumInJuels,
address billingToken,
uint96 linkUSD,
uint96 nativeUSD,
uint96 billingUSD
) = abi.decode(l1.data, (uint96, uint96, uint96, uint96, address, uint96, uint96, uint96));

assertEq(gasChargeInBillingToken, balance);
assertEq(gasReimbursementInJuels, (balance * billingUSD) / linkUSD);
assertEq(premiumInJuels, 0);
assertEq(premiumInBillingToken, 0);
}

function test_handlesInsufficientBalanceWithUSDToken6() external {
// deploy and configure a registry with ON_CHAIN payout
(Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN);

// register an upkeep and add funds
uint256 upkeepID = registry.registerUpkeep(
address(TARGET1),
1000000,
UPKEEP_ADMIN,
0,
address(usdToken6),
"",
"",
""
);
vm.prank(OWNER);
usdToken6.mint(UPKEEP_ADMIN, 1e20);

vm.startPrank(UPKEEP_ADMIN);
usdToken6.approve(address(registry), 1e20);
registry.addFunds(upkeepID, 100); // this is greater than gasCharge but less than (gasCharge + premium)
uint256 balance = registry.getBalance(upkeepID);

// manually create a transmit
vm.recordLogs();
_transmit(upkeepID, registry);
Vm.Log[] memory entries = vm.getRecordedLogs();

assertEq(entries.length, 3);
Vm.Log memory l1 = entries[1];
assertEq(
l1.topics[0],
keccak256("UpkeepCharged(uint256,(uint96,uint96,uint96,uint96,address,uint96,uint96,uint96))")
);
(
uint96 gasChargeInBillingToken,
uint96 premiumInBillingToken,
uint96 gasReimbursementInJuels,
uint96 premiumInJuels,
address billingToken,
uint96 linkUSD,
uint96 nativeUSD,
uint96 billingUSD
) = abi.decode(l1.data, (uint96, uint96, uint96, uint96, address, uint96, uint96, uint96));

assertEq(premiumInJuels, (balance * billingUSD * 1e12) / linkUSD - gasReimbursementInJuels); // scale to 18 decimals
assertEq(premiumInBillingToken, (premiumInJuels * linkUSD + (billingUSD * 1e12 - 1)) / (billingUSD * 1e12));
}
}

contract MigrateReceive is SetUp {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ contract AutomationRegistry2_3 is AutomationRegistryBase2_3, OCR2Abstract, Chain
}
}
}
// record payments
// record payments to NOPs, all in LINK
s_transmitters[msg.sender].balance += transmitVars.totalReimbursement;
s_hotVars.totalPremium += transmitVars.totalPremium;
s_reserveAmounts[IERC20(address(i_link))] += transmitVars.totalReimbursement + transmitVars.totalPremium;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,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 = 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_CONDITIONAL_OVERHEAD = 98_200; // Fixed gas overhead for conditional upkeeps
uint256 internal constant REGISTRY_LOG_OVERHEAD = 122_500; // 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 @@ -60,7 +60,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 = 13_200; // Overhead per upkeep performed in batch
uint256 internal constant ACCOUNTING_PER_UPKEEP_GAS_OVERHEAD = 14_200; // Overhead per upkeep performed in batch

LinkTokenInterface internal immutable i_link;
AggregatorV3Interface internal immutable i_linkUSDFeed;
Expand Down Expand Up @@ -695,21 +695,24 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner {
uint256 gasPaymentHexaicosaUSD = (gasWei *
(paymentParams.gasLimit + paymentParams.gasOverhead) +
paymentParams.l1CostWei) * paymentParams.nativeUSD; // gasPaymentHexaicosaUSD has an extra 8 zeros because of decimals on nativeUSD feed
// gasChargeInBillingToken is scaled by the billing token's decimals
// gasChargeInBillingToken is scaled by the billing token's decimals. Round up to ensure a minimum billing token is charged for gas
receipt.gasChargeInBillingToken = SafeCast.toUint96(
(gasPaymentHexaicosaUSD * numeratorScalingFactor) /
((gasPaymentHexaicosaUSD * numeratorScalingFactor) +
(paymentParams.billingTokenParams.priceUSD * denominatorScalingFactor - 1)) /
(paymentParams.billingTokenParams.priceUSD * denominatorScalingFactor)
);
// 18 decimals: 26 decimals / 8 decimals
receipt.gasReimbursementInJuels = SafeCast.toUint96(gasPaymentHexaicosaUSD / paymentParams.linkUSD);

// premium calculation
uint256 flatFeeHexaicosaUSD = uint256(paymentParams.billingTokenParams.flatFeeMilliCents) * 1e21; // 1e13 for milliCents to attoUSD and 1e8 for attoUSD to hexaicosaUSD
uint256 premiumHexaicosaUSD = ((((gasWei * paymentParams.gasLimit) + paymentParams.l1CostWei) *
paymentParams.billingTokenParams.gasFeePPB *
paymentParams.nativeUSD) / 1e9) + flatFeeHexaicosaUSD;
// premium is scaled by the billing token's decimals
// premium is scaled by the billing token's decimals. Round up to ensure at least minimum charge
receipt.premiumInBillingToken = SafeCast.toUint96(
(premiumHexaicosaUSD * numeratorScalingFactor) /
((premiumHexaicosaUSD * numeratorScalingFactor) +
(paymentParams.billingTokenParams.priceUSD * denominatorScalingFactor - 1)) /
(paymentParams.billingTokenParams.priceUSD * denominatorScalingFactor)
);
receipt.premiumInJuels = SafeCast.toUint96(premiumHexaicosaUSD / paymentParams.linkUSD);
Expand Down Expand Up @@ -1021,21 +1024,35 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner {
// payment is in the token's native decimals
uint96 payment = receipt.gasChargeInBillingToken + receipt.premiumInBillingToken;

// scaling factors to adjust decimals between billing token and LINK
uint256 decimals = paymentParams.billingTokenParams.decimals;
uint256 scalingFactor1 = decimals < 18 ? 10 ** (18 - decimals) : 1;
uint256 scalingFactor2 = decimals > 18 ? 10 ** (decimals - 18) : 1;

// this shouldn't happen, but in rare edge cases, we charge the full balance in case the user
// can't cover the amount owed
if (balance < receipt.gasChargeInBillingToken) {
// if the user can't cover the gas fee, then direct all of the payment to the transmitter and distribute no premium to the DON
payment = balance;
receipt.gasReimbursementInJuels = SafeCast.toUint96(
(balance * paymentParams.billingTokenParams.priceUSD) / paymentParams.linkUSD
(balance * paymentParams.billingTokenParams.priceUSD * scalingFactor1) /
(paymentParams.linkUSD * scalingFactor2)
);
receipt.premiumInJuels = 0;
receipt.premiumInBillingToken = 0;
receipt.gasChargeInBillingToken = balance;
} else if (balance < payment) {
// if the user can cover the gas fee, but not the premium, then reduce the premium
payment = balance;
receipt.premiumInJuels = SafeCast.toUint96(
((balance * paymentParams.billingTokenParams.priceUSD) / paymentParams.linkUSD) -
receipt.gasReimbursementInJuels
((balance * paymentParams.billingTokenParams.priceUSD * scalingFactor1) /
(paymentParams.linkUSD * scalingFactor2)) - receipt.gasReimbursementInJuels
);
// round up
receipt.premiumInBillingToken = SafeCast.toUint96(
((receipt.premiumInJuels * paymentParams.linkUSD * scalingFactor2) +
(paymentParams.billingTokenParams.priceUSD * scalingFactor1 - 1)) /
(paymentParams.billingTokenParams.priceUSD * scalingFactor1)
);
}

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_025_000
const transmitGasOverhead = 1_040_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.

Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ automation_registrar_wrapper2_3: ../../contracts/solc/v0.8.19/AutomationRegistra
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 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 acee8aca275f0aaeae781a505eacb59414bb685725a8af199c71a01f54739784
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 fbf6f6cf4e6858855ff5da847c3baa4859dd997cfae51f2fa0651e4fa15b92c9
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 6bab795655521b2fee8425b52f567b7a3f5d9e63b36b9a31f165af59636201c1
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 10078161924b38cf968ceb65f54078412832ada9abeebcd011ee7291811921c2
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 Down

0 comments on commit f3bbe6e

Please sign in to comment.