Skip to content

Commit

Permalink
Merge branch 'ccip-develop' into will/usdc-rate-limit-comment
Browse files Browse the repository at this point in the history
  • Loading branch information
winder authored Apr 2, 2024
2 parents a8d5e5e + ce5b690 commit 151545f
Show file tree
Hide file tree
Showing 96 changed files with 1,226 additions and 2,126 deletions.
5 changes: 5 additions & 0 deletions .changeset/eleven-singers-march.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"ccip": patch
---

support parallel execution of batched rpc calls
5 changes: 5 additions & 0 deletions .changeset/fresh-oranges-brake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"chainlink": minor
---

fix jfpc cache cleanup
5 changes: 5 additions & 0 deletions .changeset/green-fishes-fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"ccip": patch
---

remove inflight cache from commit plugin
5 changes: 5 additions & 0 deletions .changeset/many-pigs-brake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"ccip": patch
---

fix rebalancing algorithm determinism
60 changes: 57 additions & 3 deletions .github/workflows/solidity-foundry.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ on: [pull_request]

env:
FOUNDRY_PROFILE: ci
# Has to match the `make foundry` version in `contracts/GNUmakefile`
FOUNDRY_VERSION: nightly-2cb875799419c907cc3709e586ece2559e6b340e

jobs:
changes:
Expand Down Expand Up @@ -58,9 +60,10 @@ jobs:
uses: ./.github/actions/setup-nodejs

- name: Install Foundry
if: needs.changes.outputs.changes == 'true'
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly
version: ${{ env.FOUNDRY_VERSION }}

- name: Run Forge build
if: ${{ needs.changes.outputs.changes == 'true' }}
Expand Down Expand Up @@ -121,8 +124,7 @@ jobs:
if: needs.changes.outputs.changes == 'true'
uses: foundry-rs/foundry-toolchain@v1
with:
# Has to match the `make foundry` version.
version: nightly-2cb875799419c907cc3709e586ece2559e6b340e
version: ${{ env.FOUNDRY_VERSION }}

- name: Run Forge build
if: needs.changes.outputs.changes == 'true'
Expand Down Expand Up @@ -152,6 +154,58 @@ jobs:
env:
FOUNDRY_PROFILE: ${{ matrix.product }}

- name: Collect Metrics
if: needs.changes.outputs.changes == 'true'
id: collect-gha-metrics
uses: smartcontractkit/push-gha-metrics-action@0281b09807758be1dcc41651e44e62b353808c47 # v2.1.0
with:
org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }}
basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }}
hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }}
this-job-name: Foundry Tests ${{ matrix.product }}
continue-on-error: true


fmt:
strategy:
fail-fast: false
matrix:
product: [ ccip ]
needs: [ changes ]
name: Forge fmt ${{ matrix.product }}
# See https://github.com/foundry-rs/foundry/issues/3827
runs-on: ubuntu-22.04

# The if statements for steps after checkout repo is workaround for
# passing required check for PRs that don't have filtered changes.
steps:
- name: Checkout the repo
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: recursive

# Only needed because we use the NPM versions of packages
# and not native Foundry. This is to make sure the dependencies
# stay in sync.
- name: Setup NodeJS
if: needs.changes.outputs.changes == 'true'
uses: ./.github/actions/setup-nodejs

- name: Install Foundry
if: needs.changes.outputs.changes == 'true'
uses: foundry-rs/foundry-toolchain@v1
with:
version: ${{ env.FOUNDRY_VERSION }}

- name: Run Forge fmt
if: needs.changes.outputs.changes == 'true'
run: |
forge fmt --check
id: fmt
working-directory: contracts
env:
FOUNDRY_PROFILE: ${{ matrix.product }}

- name: Collect Metrics
if: needs.changes.outputs.changes == 'true'
id: collect-gha-metrics
Expand Down
1 change: 1 addition & 0 deletions contracts/.prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ src/v0.5
src/v0.6
src/v0.7
**/vendor
src/v0.8/ccip/**

# Ignore TS definition and map files
**/**.d.ts
Expand Down
6 changes: 6 additions & 0 deletions contracts/foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ gas_price = 1
block_timestamp = 1234567890
block_number = 12345

[fmt]
tab_width = 2
multiline_func_header = "params_first"
sort_imports = true
single_line_statement_blocks = "preserve"

[profile.ccip]
solc_version = '0.8.19'
src = 'src/v0.8/ccip'
Expand Down
55 changes: 19 additions & 36 deletions contracts/src/v0.8/ccip/ARM.sol
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,7 @@ contract ARM is IARM, OwnerIsCreator, ITypeAndVersion {
uint16 accumulatedWeight
);
event UnvotedToCurse(
uint32 indexed configVersion,
address indexed voter,
uint8 weight,
uint32 voteCount,
bytes32 cursesHash
uint32 indexed configVersion, address indexed voter, uint8 weight, uint32 voteCount, bytes32 cursesHash
);
event SkippedUnvoteToCurse(address indexed voter, bytes32 expectedCursesHash, bytes32 actualCursesHash);
event OwnerCursed(uint256 timestamp);
Expand Down Expand Up @@ -286,11 +282,7 @@ contract ARM is IARM, OwnerIsCreator, ITypeAndVersion {
if (curserRecord.cursesHash != cursesHash) revert InvalidCursesHash(curserRecord.cursesHash, cursesHash);

emit UnvotedToCurse(
s_versionedConfig.configVersion,
curseVoteAddr,
curserRecord.weight,
curserRecord.voteCount,
cursesHash
s_versionedConfig.configVersion, curseVoteAddr, curserRecord.weight, curserRecord.voteCount, cursesHash
);
curserRecord.voteCount = 0;
curserRecord.cursesHash = 0;
Expand Down Expand Up @@ -328,9 +320,8 @@ contract ARM is IARM, OwnerIsCreator, ITypeAndVersion {
curserRecord.cursesHash,
curseVoteProgress.accumulatedWeight
);
if (
!curseVoteProgress.curseActive && curseVoteProgress.accumulatedWeight >= curseVoteProgress.curseWeightThreshold
) {
if (!curseVoteProgress.curseActive && curseVoteProgress.accumulatedWeight >= curseVoteProgress.curseWeightThreshold)
{
curseVoteProgress.curseActive = true;
emit Cursed(configVersion, block.timestamp);
}
Expand Down Expand Up @@ -377,8 +368,8 @@ contract ARM is IARM, OwnerIsCreator, ITypeAndVersion {
}

if (
s_curseVoteProgress.curseActive &&
s_curseVoteProgress.accumulatedWeight < s_curseVoteProgress.curseWeightThreshold
s_curseVoteProgress.curseActive
&& s_curseVoteProgress.accumulatedWeight < s_curseVoteProgress.curseWeightThreshold
) {
s_curseVoteProgress.curseActive = false;
emit RecoveredFromCurse();
Expand Down Expand Up @@ -420,9 +411,11 @@ contract ARM is IARM, OwnerIsCreator, ITypeAndVersion {
/// @return accumulatedWeight sum of weights of voters, will be zero if voting took place with an older config version
/// @return blessed will be accurate regardless of when voting took place
/// @dev This is a helper method for offchain code so efficiency is not really a concern.
function getBlessProgress(
IARM.TaggedRoot calldata taggedRoot
) external view returns (address[] memory blessVoteAddrs, uint16 accumulatedWeight, bool blessed) {
function getBlessProgress(IARM.TaggedRoot calldata taggedRoot)
external
view
returns (address[] memory blessVoteAddrs, uint16 accumulatedWeight, bool blessed)
{
bytes32 taggedRootHash = _taggedRootHash(taggedRoot);
BlessVoteProgress memory progress = s_blessVoteProgressByTaggedRootHash[taggedRootHash];
blessed = progress.weightThresholdMet;
Expand Down Expand Up @@ -481,10 +474,8 @@ contract ARM is IARM, OwnerIsCreator, ITypeAndVersion {

function _validateConfig(Config memory config) internal pure returns (bool) {
if (
config.voters.length == 0 ||
config.voters.length > MAX_NUM_VOTERS ||
config.blessWeightThreshold == 0 ||
config.curseWeightThreshold == 0
config.voters.length == 0 || config.voters.length > MAX_NUM_VOTERS || config.blessWeightThreshold == 0
|| config.curseWeightThreshold == 0
) {
return false;
}
Expand All @@ -495,10 +486,8 @@ contract ARM is IARM, OwnerIsCreator, ITypeAndVersion {
for (uint256 i = 0; i < config.voters.length; ++i) {
Voter memory voter = config.voters[i];
if (
voter.blessVoteAddr == address(0) ||
voter.curseVoteAddr == address(0) ||
voter.curseUnvoteAddr == address(0) ||
(voter.blessWeight == 0 && voter.curseWeight == 0)
voter.blessVoteAddr == address(0) || voter.curseVoteAddr == address(0) || voter.curseUnvoteAddr == address(0)
|| (voter.blessWeight == 0 && voter.curseWeight == 0)
) {
return false;
}
Expand Down Expand Up @@ -547,11 +536,8 @@ contract ARM is IARM, OwnerIsCreator, ITypeAndVersion {

for (uint8 i = 0; i < config.voters.length; ++i) {
Voter memory voter = config.voters[i];
s_blesserRecords[voter.blessVoteAddr] = BlesserRecord({
configVersion: configVersion,
index: i,
weight: voter.blessWeight
});
s_blesserRecords[voter.blessVoteAddr] =
BlesserRecord({configVersion: configVersion, index: i, weight: voter.blessWeight});
s_curserRecords[voter.curseVoteAddr] = CurserRecord({
active: true,
weight: voter.curseWeight,
Expand All @@ -563,11 +549,8 @@ contract ARM is IARM, OwnerIsCreator, ITypeAndVersion {
s_versionedConfig.blockNumber = uint32(block.number);
emit ConfigSet(configVersion, config);

CurseVoteProgress memory newCurseVoteProgress = CurseVoteProgress({
curseWeightThreshold: config.curseWeightThreshold,
accumulatedWeight: 0,
curseActive: false
});
CurseVoteProgress memory newCurseVoteProgress =
CurseVoteProgress({curseWeightThreshold: config.curseWeightThreshold, accumulatedWeight: 0, curseActive: false});

// Retain votes for the cursers who are still part of the new config and delete records for the cursers who are not.
for (uint8 i = 0; i < oldConfig.voters.length; ++i) {
Expand Down
8 changes: 2 additions & 6 deletions contracts/src/v0.8/ccip/ARMProxy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,7 @@ contract ARMProxy is OwnerIsCreator, ITypeAndVersion {
assembly {
// Revert if no contract present at destination address, otherwise call
// might succeed unintentionally.
if iszero(extcodesize(arm)) {
revert(0, 0)
}
if iszero(extcodesize(arm)) { revert(0, 0) }
// We use memory starting at zero, overwriting anything that might already
// be stored there. This messes with Solidity's expectations around memory
// layout, but it's fine because we always exit execution of this contract
Expand All @@ -69,9 +67,7 @@ contract ARMProxy is OwnerIsCreator, ITypeAndVersion {
// Copy the returned data.
returndatacopy(0, 0, returndatasize())
// Pass through successful return or revert and associated data.
if success {
return(0, returndatasize())
}
if success { return(0, returndatasize()) }
revert(0, returndatasize())
}
}
Expand Down
26 changes: 12 additions & 14 deletions contracts/src/v0.8/ccip/CommitStore.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
pragma solidity 0.8.19;

import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol";
import {ICommitStore} from "./interfaces/ICommitStore.sol";
import {IARM} from "./interfaces/IARM.sol";
import {ICommitStore} from "./interfaces/ICommitStore.sol";
import {IPriceRegistry} from "./interfaces/IPriceRegistry.sol";

import {OCR2Base} from "./ocr/OCR2Base.sol";
import {Internal} from "./libraries/Internal.sol";
import {MerkleMultiProof} from "./libraries/MerkleMultiProof.sol";
import {OCR2Base} from "./ocr/OCR2Base.sol";

contract CommitStore is ICommitStore, ITypeAndVersion, OCR2Base {
error StaleReport();
Expand Down Expand Up @@ -88,10 +88,8 @@ contract CommitStore is ICommitStore, ITypeAndVersion, OCR2Base {
/// will either be ignored (reverted as an invalid interval) or will be accepted as an additional valid price update.
constructor(StaticConfig memory staticConfig) OCR2Base(false) {
if (
staticConfig.onRamp == address(0) ||
staticConfig.chainSelector == 0 ||
staticConfig.sourceChainSelector == 0 ||
staticConfig.armProxy == address(0)
staticConfig.onRamp == address(0) || staticConfig.chainSelector == 0 || staticConfig.sourceChainSelector == 0
|| staticConfig.armProxy == address(0)
) revert InvalidCommitStoreConfig();

i_chainSelector = staticConfig.chainSelector;
Expand Down Expand Up @@ -207,8 +205,9 @@ contract CommitStore is ICommitStore, ITypeAndVersion, OCR2Base {
}

// If we reached this section, the report should contain a valid root
if (s_minSeqNr != report.interval.min || report.interval.min > report.interval.max)
if (s_minSeqNr != report.interval.min || report.interval.min > report.interval.max) {
revert InvalidInterval(report.interval);
}

if (report.merkleRoot == bytes32(0)) revert InvalidRoot();
// Disallow duplicate roots as that would reset the timestamp and
Expand All @@ -228,13 +227,12 @@ contract CommitStore is ICommitStore, ITypeAndVersion, OCR2Base {
/// @dev RMN depends on this function, if changing, please notify the RMN maintainers.
/// @return the configuration.
function getStaticConfig() external view returns (StaticConfig memory) {
return
StaticConfig({
chainSelector: i_chainSelector,
sourceChainSelector: i_sourceChainSelector,
onRamp: i_onRamp,
armProxy: i_armProxy
});
return StaticConfig({
chainSelector: i_chainSelector,
sourceChainSelector: i_sourceChainSelector,
onRamp: i_onRamp,
armProxy: i_armProxy
});
}

/// @notice Returns the dynamic commit store config.
Expand Down
Loading

0 comments on commit 151545f

Please sign in to comment.