Skip to content

Commit

Permalink
Merge branch 'ccip-develop' into ccip-2645
Browse files Browse the repository at this point in the history
  • Loading branch information
b-gopalswami authored Jul 16, 2024
2 parents b77d561 + f77e6f0 commit 12c5799
Show file tree
Hide file tree
Showing 46 changed files with 1,187 additions and 542 deletions.
9 changes: 5 additions & 4 deletions .github/workflows/ci-core.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,19 @@ jobs:
type:
- cmd: go_core_tests
id: core_unit
os: ubuntu22.04-32cores-128GB
- cmd: go_core_race_tests
id: core_race
# use 64cores for overnight runs only due to massive number of runs from PRs
os: ${{ github.event_name == 'schedule' && 'ubuntu-latest-64cores-256GB' || 'ubuntu-latest-32cores-128GB' }}
- cmd: go_core_fuzz
id: core_fuzz
os: ubuntu22.04-8cores-32GB
name: Core Tests (${{ matrix.type.cmd }})
# We don't directly merge dependabot PRs, so let's not waste the resources
if: github.actor != 'dependabot[bot]'
needs: [filter]
runs-on: ubuntu-latest-64cores-256GB
runs-on: ${{ matrix.type.os }}
steps:
- name: Checkout the repo
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
Expand All @@ -113,9 +117,6 @@ jobs:
- name: Setup Go
if: ${{ needs.filter.outputs.changes == 'true' }}
uses: ./.github/actions/setup-go
- name: Run short tests
if: ${{ needs.filter.outputs.changes == 'true' && matrix.type.cmd == 'go_core_tests' }}
run: go test -short ./...
- name: Setup Solana
if: ${{ needs.filter.outputs.changes == 'true' }}
uses: ./.github/actions/setup-solana
Expand Down
13 changes: 6 additions & 7 deletions .github/workflows/stale.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
# Workflow is triggered daily midnight UTC
# A PR with more than 60 days of inactivity will be marked as stale
# A PR that's stale for more than 7 days will be automatically closed
# Issues are exempt from auto marking as stale but issues with manually added 'stale' label are eligible for auto closure after 7 days.
# PRs with assignees are exempt from auto stale marking, it's the responsibility of the assignee to get the PR progressed either with review/merge or closure.
# Workflow to manage automatically closing stale pull requests and issues.
# See configuration for configuration.
name: Manage stale Issues and PRs

on:
Expand All @@ -21,6 +18,8 @@ jobs:
- uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
exempt-all-pr-assignees: true
stale-pr-message: 'This PR is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days.'
days-before-issue-stale: -1 # disables marking issues as stale automatically. Issues can still be marked as stale manually, in which the closure policy applies.
stale-pr-message: 'This PR is stale because it has been open 45 days with no activity. Remove stale label or comment or this will be closed in 10 days.'
close-pr-message: 'This PR was closed because it has been stalled for 10 days with no activity.'
days-before-pr-stale: 45
days-before-pr-close: 10
595 changes: 298 additions & 297 deletions contracts/gas-snapshots/ccip.gas-snapshot

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions contracts/gas-snapshots/liquiditymanager.gas-snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ LiquidityManager_addLiquidity:test_addLiquiditySuccess() (gas: 279154)
LiquidityManager_rebalanceLiquidity:test_InsufficientLiquidityReverts() (gas: 206745)
LiquidityManager_rebalanceLiquidity:test_InvalidRemoteChainReverts() (gas: 192319)
LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPoolsSuccess() (gas: 9141768)
LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPoolsSuccess_AlreadyFinalized() (gas: 8899695)
LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPools_MultiStageFinalization() (gas: 8894901)
LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPools_NativeRewrap() (gas: 8822699)
LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPoolsSuccess_AlreadyFinalized() (gas: 8898695)
LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPools_MultiStageFinalization() (gas: 8893901)
LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPools_NativeRewrap() (gas: 8821699)
LiquidityManager_rebalanceLiquidity:test_rebalanceLiquiditySuccess() (gas: 382897)
LiquidityManager_receive:test_receive_success() (gas: 21182)
LiquidityManager_removeLiquidity:test_InsufficientLiquidityReverts() (gas: 184869)
Expand All @@ -19,7 +19,7 @@ LiquidityManager_setFinanceRole:test_OnlyOwnerReverts() (gas: 10987)
LiquidityManager_setFinanceRole:test_setFinanceRoleSuccess() (gas: 21836)
LiquidityManager_setLocalLiquidityContainer:test_OnlyOwnerReverts() (gas: 11052)
LiquidityManager_setLocalLiquidityContainer:test_ReverstWhen_CalledWithTheZeroAddress() (gas: 10643)
LiquidityManager_setLocalLiquidityContainer:test_setLocalLiquidityContainerSuccess() (gas: 3437651)
LiquidityManager_setLocalLiquidityContainer:test_setLocalLiquidityContainerSuccess() (gas: 3436651)
LiquidityManager_setMinimumLiquidity:test_OnlyOwnerReverts() (gas: 10925)
LiquidityManager_setMinimumLiquidity:test_setMinimumLiquiditySuccess() (gas: 36389)
LiquidityManager_withdrawERC20:test_withdrawERC20Reverts() (gas: 180359)
Expand Down
4 changes: 2 additions & 2 deletions contracts/scripts/native_solc_compile_all_ccip
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ echo " └───────────────────────
SOLC_VERSION="0.8.24"
OPTIMIZE_RUNS=26000
OPTIMIZE_RUNS_OFFRAMP=18000
OPTIMIZE_RUNS_ONRAMP=3600
OPTIMIZE_RUNS_MULTI_OFFRAMP=2400
OPTIMIZE_RUNS_ONRAMP=4100
OPTIMIZE_RUNS_MULTI_OFFRAMP=2500


SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
Expand Down
3 changes: 1 addition & 2 deletions contracts/src/v0.8/ccip/AggregateRateLimiter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ contract AggregateRateLimiter is OwnerIsCreator {
// The token bucket object that contains the bucket state.
RateLimiter.TokenBucket private s_rateLimiter;

/// @param config The RateLimiter.Config containing the capacity and refill rate
/// of the bucket, plus the admin address.
/// @param config The RateLimiter.Config
constructor(RateLimiter.Config memory config) {
s_rateLimiter = RateLimiter.TokenBucket({
rate: config.rate,
Expand Down
35 changes: 8 additions & 27 deletions contracts/src/v0.8/ccip/libraries/Internal.sol
Original file line number Diff line number Diff line change
Expand Up @@ -131,19 +131,6 @@ library Internal {
/// When abi encoded, each token transfer takes up 7 slots, excl bytes contents.
uint256 public constant ANY_2_EVM_MESSAGE_FIXED_BYTES_PER_TOKEN = 32 * 7;

function _toAny2EVMMessage(
EVM2EVMMessage memory original,
Client.EVMTokenAmount[] memory destTokenAmounts
) internal pure returns (Client.Any2EVMMessage memory message) {
return Client.Any2EVMMessage({
messageId: original.messageId,
sourceChainSelector: original.sourceChainSelector,
sender: abi.encode(original.sender),
data: original.data,
destTokenAmounts: destTokenAmounts
});
}

bytes32 internal constant EVM_2_EVM_MESSAGE_HASH = keccak256("EVM2EVMMessageHashV2");

/// @dev Used to hash messages for single-lane ramps.
Expand Down Expand Up @@ -239,27 +226,21 @@ library Internal {
);
}

/// @dev We disallow the first 1024 addresses to never allow calling precompiles. It is extremely unlikely that
/// anyone would ever be able to generate an address in this range.
uint256 public constant PRECOMPILE_SPACE = 1024;

/// @notice This methods provides validation for parsing abi encoded addresses by ensuring the
/// address is within the EVM address space. If it isn't it will revert with an InvalidEVMAddress error, which
/// we can catch and handle more gracefully than a revert from abi.decode.
/// @return The address if it is valid, the function will revert otherwise.
function _validateEVMAddress(bytes memory encodedAddress) internal pure returns (address) {
if (encodedAddress.length != 32) revert InvalidEVMAddress(encodedAddress);
return _validateEVMAddressFromUint256(abi.decode(encodedAddress, (uint256)));
}

/// @dev We disallow the first 1024 addresses to never allow calling precompiles. It is extremely unlikely that
/// anyone would ever be able to generate an address in this range.
uint256 public constant PRECOMPILE_SPACE = 1024;

/// @notice This method provides a safe way to convert a uint256 to an address.
/// It will revert if the uint256 is not a valid EVM address, or a precompile address.
/// @return The address if it is valid, the function will revert otherwise.
function _validateEVMAddressFromUint256(uint256 encodedAddress) internal pure returns (address) {
if (encodedAddress > type(uint160).max || encodedAddress < PRECOMPILE_SPACE) {
revert InvalidEVMAddress(abi.encode(encodedAddress));
uint256 encodedAddressUint = abi.decode(encodedAddress, (uint256));
if (encodedAddressUint > type(uint160).max || encodedAddressUint < PRECOMPILE_SPACE) {
revert InvalidEVMAddress(encodedAddress);
}
return address(uint160(encodedAddress));
return address(uint160(encodedAddressUint));
}

/// @notice Enum listing the possible message execution states within
Expand Down
67 changes: 44 additions & 23 deletions contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
error AlreadyAttempted(uint64 sourceChainSelector, uint64 sequenceNumber);
error AlreadyExecuted(uint64 sourceChainSelector, uint64 sequenceNumber);
error ZeroChainSelectorNotAllowed();
error ExecutionError(bytes32 messageId, bytes error);
error ExecutionError(bytes32 messageId, bytes err);
error SourceChainNotEnabled(uint64 sourceChainSelector);
error TokenDataMismatch(uint64 sourceChainSelector, uint64 sequenceNumber);
error UnexpectedTokenData();
Expand All @@ -47,8 +47,8 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
error RootAlreadyCommitted(uint64 sourceChainSelector, bytes32 merkleRoot);
error InvalidRoot();
error CanOnlySelfCall();
error ReceiverError(bytes error);
error TokenHandlingError(bytes error);
error ReceiverError(bytes err);
error TokenHandlingError(bytes err);
error EmptyReport();
error CursedByRMN(uint64 sourceChainSelector);
error NotACompatiblePool(address notPool);
Expand Down Expand Up @@ -169,7 +169,11 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
/// @dev The sequence number of the last price update
uint64 private s_latestPriceSequenceNumber;

constructor(StaticConfig memory staticConfig, SourceChainConfigArgs[] memory sourceChainConfigs) MultiOCR3Base() {
constructor(
StaticConfig memory staticConfig,
DynamicConfig memory dynamicConfig,
SourceChainConfigArgs[] memory sourceChainConfigs
) MultiOCR3Base() {
if (
staticConfig.rmnProxy == address(0) || staticConfig.tokenAdminRegistry == address(0)
|| staticConfig.nonceManager == address(0)
Expand All @@ -187,6 +191,7 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
i_nonceManager = staticConfig.nonceManager;
emit StaticConfigSet(staticConfig);

_setDynamicConfig(dynamicConfig);
_applySourceChainConfigUpdates(sourceChainConfigs);
}

Expand Down Expand Up @@ -279,8 +284,10 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
for (uint256 msgIndex = 0; msgIndex < numMsgs; ++msgIndex) {
uint256 newLimit = msgGasLimitOverrides[msgIndex];
// Checks to ensure message cannot be executed with less gas than specified.
if (newLimit != 0 && newLimit < report.messages[msgIndex].gasLimit) {
revert InvalidManualExecutionGasLimit(report.sourceChainSelector, msgIndex, newLimit);
if (newLimit != 0) {
if (newLimit < report.messages[msgIndex].gasLimit) {
revert InvalidManualExecutionGasLimit(report.sourceChainSelector, msgIndex, newLimit);
}
}
}
}
Expand Down Expand Up @@ -412,11 +419,15 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
// FAILURE -> FAILURE no nonce bump
// FAILURE -> SUCCESS no nonce bump
// UNTOUCHED messages MUST be executed in order always
if (message.header.nonce > 0 && originalState == Internal.MessageExecutionState.UNTOUCHED) {
// If a nonce is not incremented, that means it was skipped, and we can ignore the message
if (
!INonceManager(i_nonceManager).incrementInboundNonce(sourceChainSelector, message.header.nonce, message.sender)
) continue;
if (message.header.nonce != 0) {
if (originalState == Internal.MessageExecutionState.UNTOUCHED) {
// If a nonce is not incremented, that means it was skipped, and we can ignore the message
if (
!INonceManager(i_nonceManager).incrementInboundNonce(
sourceChainSelector, message.header.nonce, message.sender
)
) continue;
}
}

// Although we expect only valid messages will be committed, we check again
Expand All @@ -433,19 +444,22 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
// Since it's hard to estimate whether manual execution will succeed, we
// revert the entire transaction if it fails. This will show the user if
// their manual exec will fail before they submit it.
if (
manualExecution && newState == Internal.MessageExecutionState.FAILURE
&& originalState != Internal.MessageExecutionState.UNTOUCHED
) {
// If manual execution fails, we revert the entire transaction, unless the originalState is UNTOUCHED as we
// would still be making progress by changing the state from UNTOUCHED to FAILURE.
revert ExecutionError(message.header.messageId, returnData);
if (manualExecution) {
if (newState == Internal.MessageExecutionState.FAILURE) {
if (originalState != Internal.MessageExecutionState.UNTOUCHED) {
// If manual execution fails, we revert the entire transaction, unless the originalState is UNTOUCHED as we
// would still be making progress by changing the state from UNTOUCHED to FAILURE.
revert ExecutionError(message.header.messageId, returnData);
}
}
}

// The only valid prior states are UNTOUCHED and FAILURE (checked above)
// The only valid post states are FAILURE and SUCCESS (checked below)
if (newState != Internal.MessageExecutionState.FAILURE && newState != Internal.MessageExecutionState.SUCCESS) {
revert InvalidNewState(sourceChainSelector, message.header.sequenceNumber, newState);
if (newState != Internal.MessageExecutionState.SUCCESS) {
if (newState != Internal.MessageExecutionState.FAILURE) {
revert InvalidNewState(sourceChainSelector, message.header.sequenceNumber, newState);
}
}

emit ExecutionStateChanged(
Expand Down Expand Up @@ -750,7 +764,14 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
}

/// @notice Sets the dynamic config.
/// @param dynamicConfig The new dynamic config.
function setDynamicConfig(DynamicConfig memory dynamicConfig) external onlyOwner {
_setDynamicConfig(dynamicConfig);
}

/// @notice Sets the dynamic config.
/// @param dynamicConfig The dynamic config.
function _setDynamicConfig(DynamicConfig memory dynamicConfig) internal {
if (dynamicConfig.priceRegistry == address(0) || dynamicConfig.router == address(0)) {
revert ZeroAddressNotAllowed();
}
Expand Down Expand Up @@ -814,8 +835,8 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
// We call the pool with exact gas to increase resistance against malicious tokens or token pools.
// We protects against return data bombs by capping the return data size at MAX_RET_BYTES.
(bool success, bytes memory returnData,) = CallWithExactGas._callWithExactGasSafeReturnData(
abi.encodeWithSelector(
IPoolV1.releaseOrMint.selector,
abi.encodeCall(
IPoolV1.releaseOrMint,
Pool.ReleaseOrMintInV1({
originalSender: originalSender,
receiver: receiver,
Expand Down Expand Up @@ -845,7 +866,7 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
// transfer them to the final receiver. We use the _callWithExactGasSafeReturnData function because
// the token contracts are not considered trusted.
(success, returnData,) = CallWithExactGas._callWithExactGasSafeReturnData(
abi.encodeWithSelector(IERC20.transfer.selector, receiver, localAmount),
abi.encodeCall(IERC20.transfer, (receiver, localAmount)),
localToken,
s_dynamicConfig.maxTokenTransferGas,
Internal.GAS_FOR_CALL_EXACT_CHECK,
Expand Down
Loading

0 comments on commit 12c5799

Please sign in to comment.