Skip to content

Commit

Permalink
Merge branch 'develop' into fixLiveTestReporting
Browse files Browse the repository at this point in the history
  • Loading branch information
Tofel authored Jan 25, 2024
2 parents e67d5c0 + e9f138c commit bd8ff54
Show file tree
Hide file tree
Showing 29 changed files with 327 additions and 89 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ jobs:
os: ubuntu-latest
pyroscope_env: ci-smoke-vrf-evm-simulated
- name: vrfv2
nodes: 2
nodes: 3
os: ubuntu-latest
pyroscope_env: ci-smoke-vrf2-evm-simulated
- name: vrfv2plus
Expand Down
3 changes: 3 additions & 0 deletions GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,15 @@ godoc: ## Install and run godoc
install-chainlink: operator-ui ## Install the chainlink binary.
go install $(GOFLAGS) .

.PHONY: chainlink
chainlink: ## Build the chainlink binary.
go build $(GOFLAGS) .

.PHONY: chainlink-dev
chainlink-dev: ## Build a dev build of chainlink binary.
go build -tags dev $(GOFLAGS) .

.PHONY: chainlink-test
chainlink-test: ## Build a test build of chainlink binary.
go build $(GOFLAGS) .

Expand Down

Large diffs are not rendered by default.

189 changes: 189 additions & 0 deletions contracts/src/v0.8/automation/dev/test/AutomationRegistry2_2.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.16;

import {AutomationForwarderLogic} from "../../AutomationForwarderLogic.sol";
import {BaseTest} from "./BaseTest.t.sol";
import {AutomationRegistry2_2} from "../v2_2/AutomationRegistry2_2.sol";
import {AutomationRegistryBase2_2} from "../v2_2/AutomationRegistryBase2_2.sol";
import {AutomationRegistryLogicA2_2} from "../v2_2/AutomationRegistryLogicA2_2.sol";
import {AutomationRegistryLogicB2_2} from "../v2_2/AutomationRegistryLogicB2_2.sol";
import {IAutomationRegistryMaster} from "../interfaces/v2_2/IAutomationRegistryMaster.sol";

contract AutomationRegistry2_2_SetUp is BaseTest {
address internal constant LINK_ETH_FEED = 0x1111111111111111111111111111111111111110;
address internal constant FAST_GAS_FEED = 0x1111111111111111111111111111111111111112;
address internal constant LINK_TOKEN = 0x1111111111111111111111111111111111111113;

// Signer private keys used for these test
uint256 internal constant PRIVATE0 = 0x7b2e97fe057e6de99d6872a2ef2abf52c9b4469bc848c2465ac3fcd8d336e81d;
uint256 internal constant PRIVATE1 = 0xab56160806b05ef1796789248e1d7f34a6465c5280899159d645218cd216cee6;
uint256 internal constant PRIVATE2 = 0x6ec7caa8406a49b76736602810e0a2871959fbbb675e23a8590839e4717f1f7f;
uint256 internal constant PRIVATE3 = 0x80f14b11da94ae7f29d9a7713ea13dc838e31960a5c0f2baf45ed458947b730a;

uint64 internal constant OFFCHAIN_CONFIG_VERSION = 30; // 2 for OCR2
uint8 internal constant F = 1;

address[] internal s_valid_signers;
address[] internal s_valid_transmitters;
address[] internal s_registrars;

function setUp() public override {
s_valid_transmitters = new address[](4);
for (uint160 i = 0; i < 4; ++i) {
s_valid_transmitters[i] = address(4 + i);
}

s_valid_signers = new address[](4);
s_valid_signers[0] = vm.addr(PRIVATE0); //0xc110458BE52CaA6bB68E66969C3218A4D9Db0211
s_valid_signers[1] = vm.addr(PRIVATE1); //0xc110a19c08f1da7F5FfB281dc93630923F8E3719
s_valid_signers[2] = vm.addr(PRIVATE2); //0xc110fdF6e8fD679C7Cc11602d1cd829211A18e9b
s_valid_signers[3] = vm.addr(PRIVATE3); //0xc11028017c9b445B6bF8aE7da951B5cC28B326C0

s_registrars = new address[](1);
s_registrars[0] = 0x3a0eDE26aa188BFE00b9A0C9A431A1a0CA5f7966;
}

function deployRegistry2_2(AutomationRegistryBase2_2.Mode mode) public returns (IAutomationRegistryMaster) {
AutomationForwarderLogic forwarderLogic = new AutomationForwarderLogic();
AutomationRegistryLogicB2_2 logicB2_2 = new AutomationRegistryLogicB2_2(
mode,
LINK_TOKEN,
LINK_ETH_FEED,
FAST_GAS_FEED,
address(forwarderLogic)
);
AutomationRegistryLogicA2_2 logicA2_2 = new AutomationRegistryLogicA2_2(logicB2_2);
IAutomationRegistryMaster registry2_2 = IAutomationRegistryMaster(
address(new AutomationRegistry2_2(AutomationRegistryLogicB2_2(address(logicA2_2))))
);
return registry2_2;
}
}

contract AutomationRegistry2_2_LatestConfigDetails is AutomationRegistry2_2_SetUp {
function testGet() public {
IAutomationRegistryMaster registry = IAutomationRegistryMaster(
address(deployRegistry2_2(AutomationRegistryBase2_2.Mode(0)))
);
(uint32 configCount, uint32 blockNumber, bytes32 configDigest) = registry.latestConfigDetails();
assertEq(configCount, 0);
assertEq(blockNumber, 0);
assertEq(configDigest, "");
}
}

contract AutomationRegistry2_2_SetConfig is AutomationRegistry2_2_SetUp {
event ConfigSet(
uint32 previousConfigBlockNumber,
bytes32 configDigest,
uint64 configCount,
address[] signers,
address[] transmitters,
uint8 f,
bytes onchainConfig,
uint64 offchainConfigVersion,
bytes offchainConfig
);

function testSetConfigSuccess() public {
IAutomationRegistryMaster registry = IAutomationRegistryMaster(
address(deployRegistry2_2(AutomationRegistryBase2_2.Mode(0)))
);
(uint32 configCount, , ) = registry.latestConfigDetails();
assertEq(configCount, 0);

AutomationRegistryBase2_2.OnchainConfig memory cfg = AutomationRegistryBase2_2.OnchainConfig({
paymentPremiumPPB: 10_000,
flatFeeMicroLink: 40_000,
checkGasLimit: 5_000_000,
stalenessSeconds: 90_000,
gasCeilingMultiplier: 0,
minUpkeepSpend: 0,
maxPerformGas: 10_000_000,
maxCheckDataSize: 5_000,
maxPerformDataSize: 5_000,
maxRevertDataSize: 5_000,
fallbackGasPrice: 20_000_000_000,
fallbackLinkPrice: 200_000_000_000,
transcoder: 0xB1e66855FD67f6e85F0f0fA38cd6fBABdf00923c,
registrars: s_registrars,
upkeepPrivilegeManager: 0xD9c855F08A7e460691F41bBDDe6eC310bc0593D8,
reorgProtectionEnabled: true
});
bytes memory onchainConfigBytes = abi.encode(cfg);

uint256 a = 1234;
address b = address(0);
bytes memory offchainConfigBytes = abi.encode(a, b);
bytes32 configDigest = _configDigestFromConfigData(
block.chainid,
address(registry),
++configCount,
s_valid_signers,
s_valid_transmitters,
F,
onchainConfigBytes,
OFFCHAIN_CONFIG_VERSION,
offchainConfigBytes
);

vm.expectEmit();
emit ConfigSet(
0,
configDigest,
configCount,
s_valid_signers,
s_valid_transmitters,
F,
onchainConfigBytes,
OFFCHAIN_CONFIG_VERSION,
offchainConfigBytes
);

registry.setConfig(
s_valid_signers,
s_valid_transmitters,
F,
onchainConfigBytes,
OFFCHAIN_CONFIG_VERSION,
offchainConfigBytes
);

(, , address[] memory signers, address[] memory transmitters, uint8 f) = registry.getState();

assertEq(signers, s_valid_signers);
assertEq(transmitters, s_valid_transmitters);
assertEq(f, F);
}

function _configDigestFromConfigData(
uint256 chainId,
address contractAddress,
uint64 configCount,
address[] memory signers,
address[] memory transmitters,
uint8 f,
bytes memory onchainConfig,
uint64 offchainConfigVersion,
bytes memory offchainConfig
) internal pure returns (bytes32) {
uint256 h = uint256(
keccak256(
abi.encode(
chainId,
contractAddress,
configCount,
signers,
transmitters,
f,
onchainConfig,
offchainConfigVersion,
offchainConfig
)
)
);
uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00
uint256 prefix = 0x0001 << (256 - 16); // 0x000100..00
return bytes32((prefix & prefixMask) | (h & ~prefixMask));
}
}
13 changes: 13 additions & 0 deletions contracts/src/v0.8/automation/dev/test/BaseTest.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.16;

import "forge-std/Test.sol";

contract BaseTest is Test {
address internal OWNER = 0x00007e64E1fB0C487F25dd6D3601ff6aF8d32e4e;

function setUp() public virtual {
vm.startPrank(OWNER);
deal(OWNER, 1e20);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ contract AutomationRegistry2_2 is AutomationRegistryBase2_2, OCR2Abstract, Chain
(upkeepTransmitInfo[i].earlyChecksPassed, upkeepTransmitInfo[i].dedupID) = _prePerformChecks(
report.upkeepIds[i],
report.triggers[i],
upkeepTransmitInfo[i]
upkeepTransmitInfo[i],
hotVars
);

if (upkeepTransmitInfo[i].earlyChecksPassed) {
Expand Down Expand Up @@ -308,7 +309,8 @@ contract AutomationRegistry2_2 is AutomationRegistryBase2_2, OCR2Abstract, Chain
paused: s_hotVars.paused,
reentrancyGuard: s_hotVars.reentrancyGuard,
totalPremium: totalPremium,
latestEpoch: 0 // DON restarts epoch
latestEpoch: 0, // DON restarts epoch
reorgProtectionEnabled: onchainConfig.reorgProtectionEnabled
});

s_storage = Storage({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ abstract contract AutomationRegistryBase2_2 is ConfirmedOwner, ExecutionPreventi
* @member transcoder address of the transcoder contract
* @member registrars addresses of the registrar contracts
* @member upkeepPrivilegeManager address which can set privilege for upkeeps
* @member reorgProtectionEnabled if this registry will enable re-org protection checks
*/
struct OnchainConfig {
uint32 paymentPremiumPPB;
Expand All @@ -225,6 +226,7 @@ abstract contract AutomationRegistryBase2_2 is ConfirmedOwner, ExecutionPreventi
address transcoder;
address[] registrars;
address upkeepPrivilegeManager;
bool reorgProtectionEnabled;
}

/**
Expand Down Expand Up @@ -307,16 +309,16 @@ abstract contract AutomationRegistryBase2_2 is ConfirmedOwner, ExecutionPreventi

/// @dev Config + State storage struct which is on hot transmit path
struct HotVars {
uint8 f; // maximum number of faulty oracles
uint32 paymentPremiumPPB; // premium percentage charged to user over tx cost
uint32 flatFeeMicroLink; // flat fee charged to user for every perform
uint24 stalenessSeconds; // Staleness tolerance for feeds
uint16 gasCeilingMultiplier; // multiplier on top of fast gas feed for upper bound
bool paused; // pause switch for all upkeeps in the registry
bool reentrancyGuard; // guard against reentrancy
uint96 totalPremium; // total historical payment to oracles for premium
uint32 latestEpoch; // latest epoch for which a report was transmitted
// 1 EVM word full
uint96 totalPremium; // ─────────╮ total historical payment to oracles for premium
uint32 paymentPremiumPPB; // premium percentage charged to user over tx cost
uint32 flatFeeMicroLink; // flat fee charged to user for every perform
uint32 latestEpoch; // │ latest epoch for which a report was transmitted
uint24 stalenessSeconds; // │ Staleness tolerance for feeds
uint16 gasCeilingMultiplier; // │ multiplier on top of fast gas feed for upper bound
uint8 f; // │ maximum number of faulty oracles
bool paused; // │ pause switch for all upkeeps in the registry
bool reentrancyGuard; // ────────╯ guard against reentrancy
bool reorgProtectionEnabled; // if this registry should enable re-org protection mechanism
}

/// @dev Config + State storage struct which is not on hot transmit path
Expand Down Expand Up @@ -733,14 +735,15 @@ abstract contract AutomationRegistryBase2_2 is ConfirmedOwner, ExecutionPreventi
function _prePerformChecks(
uint256 upkeepId,
bytes memory rawTrigger,
UpkeepTransmitInfo memory transmitInfo
UpkeepTransmitInfo memory transmitInfo,
HotVars memory hotVars
) internal returns (bool, bytes32) {
bytes32 dedupID;
if (transmitInfo.triggerType == Trigger.CONDITION) {
if (!_validateConditionalTrigger(upkeepId, rawTrigger, transmitInfo)) return (false, dedupID);
if (!_validateConditionalTrigger(upkeepId, rawTrigger, transmitInfo, hotVars)) return (false, dedupID);
} else if (transmitInfo.triggerType == Trigger.LOG) {
bool valid;
(valid, dedupID) = _validateLogTrigger(upkeepId, rawTrigger);
(valid, dedupID) = _validateLogTrigger(upkeepId, rawTrigger, hotVars);
if (!valid) return (false, dedupID);
} else {
revert InvalidTriggerType();
Expand All @@ -765,7 +768,8 @@ abstract contract AutomationRegistryBase2_2 is ConfirmedOwner, ExecutionPreventi
function _validateConditionalTrigger(
uint256 upkeepId,
bytes memory rawTrigger,
UpkeepTransmitInfo memory transmitInfo
UpkeepTransmitInfo memory transmitInfo,
HotVars memory hotVars
) internal returns (bool) {
ConditionalTrigger memory trigger = abi.decode(rawTrigger, (ConditionalTrigger));
if (trigger.blockNum < transmitInfo.upkeep.lastPerformedBlockNumber) {
Expand All @@ -774,7 +778,8 @@ abstract contract AutomationRegistryBase2_2 is ConfirmedOwner, ExecutionPreventi
return false;
}
if (
(trigger.blockHash != bytes32("") && _blockHash(trigger.blockNum) != trigger.blockHash) ||
(hotVars.reorgProtectionEnabled &&
(trigger.blockHash != bytes32("") && _blockHash(trigger.blockNum) != trigger.blockHash)) ||
trigger.blockNum >= _blockNum()
) {
// There are two cases of reorged report
Expand All @@ -789,11 +794,16 @@ abstract contract AutomationRegistryBase2_2 is ConfirmedOwner, ExecutionPreventi
return true;
}

function _validateLogTrigger(uint256 upkeepId, bytes memory rawTrigger) internal returns (bool, bytes32) {
function _validateLogTrigger(
uint256 upkeepId,
bytes memory rawTrigger,
HotVars memory hotVars
) internal returns (bool, bytes32) {
LogTrigger memory trigger = abi.decode(rawTrigger, (LogTrigger));
bytes32 dedupID = keccak256(abi.encodePacked(upkeepId, trigger.logBlockHash, trigger.txHash, trigger.logIndex));
if (
(trigger.blockHash != bytes32("") && _blockHash(trigger.blockNum) != trigger.blockHash) ||
(hotVars.reorgProtectionEnabled &&
(trigger.blockHash != bytes32("") && _blockHash(trigger.blockNum) != trigger.blockHash)) ||
trigger.blockNum >= _blockNum()
) {
// Reorg protection is same as conditional trigger upkeeps
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,8 @@ contract AutomationRegistryLogicB2_2 is AutomationRegistryBase2_2 {
fallbackLinkPrice: s_fallbackLinkPrice,
transcoder: s_storage.transcoder,
registrars: s_registrars.values(),
upkeepPrivilegeManager: s_storage.upkeepPrivilegeManager
upkeepPrivilegeManager: s_storage.upkeepPrivilegeManager,
reorgProtectionEnabled: s_hotVars.reorgProtectionEnabled
});

return (state, config, s_signersList, s_transmittersList, s_hotVars.f);
Expand Down
Loading

0 comments on commit bd8ff54

Please sign in to comment.