Skip to content

Instantly share code, notes, and snippets.

@TilakMaddy
Created March 29, 2024 17:33
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TilakMaddy/bf21b4de205195f6606d4e8dd4f4fa23 to your computer and use it in GitHub Desktop.
Save TilakMaddy/bf21b4de205195f6606d4e8dd4f4fa23 to your computer and use it in GitHub Desktop.
CCIP contract report

Aderyn Analysis Report

This report was generated by Aderyn, a static analysis tool built by Cyfrin, a blockchain security company. This report is not a substitute for manual audit or security review. It should not be relied upon for any purpose other than to assist in the identification of potential security vulnerabilities.

Table of Contents

Summary

Files Summary

Key Value
.sol Files 43
Total nSLOC 3718

Files Details

Filepath nSLOC
src/v0.8/ccip/ARM.sol 429
src/v0.8/ccip/ARMProxy.sol 35
src/v0.8/ccip/AggregateRateLimiter.sol 50
src/v0.8/ccip/CommitStore.sol 171
src/v0.8/ccip/PriceRegistry.sol 153
src/v0.8/ccip/Router.sol 183
src/v0.8/ccip/applications/CCIPClientExample.sol 110
src/v0.8/ccip/applications/CCIPReceiver.sol 26
src/v0.8/ccip/applications/DefensiveExample.sol 60
src/v0.8/ccip/applications/PingPongDemo.sol 74
src/v0.8/ccip/applications/SelfFundedPingPong.sol 45
src/v0.8/ccip/applications/TokenProxy.sol 52
src/v0.8/ccip/interfaces/IARM.sol 9
src/v0.8/ccip/interfaces/IAny2EVMMessageReceiver.sol 5
src/v0.8/ccip/interfaces/IAny2EVMOffRamp.sol 4
src/v0.8/ccip/interfaces/ICommitStore.sol 9
src/v0.8/ccip/interfaces/IEVM2AnyOnRamp.sol 8
src/v0.8/ccip/interfaces/IEVM2AnyOnRampClient.sol 15
src/v0.8/ccip/interfaces/IPriceRegistry.sol 20
src/v0.8/ccip/interfaces/IRouter.sol 13
src/v0.8/ccip/interfaces/IRouterClient.sol 17
src/v0.8/ccip/interfaces/IWrappedNative.sol 6
src/v0.8/ccip/interfaces/automation/ILinkAvailable.sol 4
src/v0.8/ccip/interfaces/pools/IPool.sol 19
src/v0.8/ccip/libraries/Client.sol 28
src/v0.8/ccip/libraries/Internal.sol 95
src/v0.8/ccip/libraries/MerkleMultiProof.sol 56
src/v0.8/ccip/libraries/RateLimiter.sol 96
src/v0.8/ccip/libraries/USDPriceWith18Decimals.sol 9
src/v0.8/ccip/ocr/OCR2Abstract.sol 72
src/v0.8/ccip/ocr/OCR2Base.sol 188
src/v0.8/ccip/ocr/OCR2BaseNoChecks.sol 146
src/v0.8/ccip/offRamp/EVM2EVMOffRamp.sol 389
src/v0.8/ccip/onRamp/EVM2EVMOnRamp.sol 545
src/v0.8/ccip/pools/BurnFromMintTokenPool.sol 21
src/v0.8/ccip/pools/BurnMintTokenPool.sol 17
src/v0.8/ccip/pools/BurnMintTokenPoolAbstract.sol 37
src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol 21
src/v0.8/ccip/pools/LockReleaseTokenPool.sol 101
src/v0.8/ccip/pools/TokenPool.sol 207
src/v0.8/ccip/pools/USDC/IMessageTransmitter.sol 6
src/v0.8/ccip/pools/USDC/ITokenMessenger.sol 22
src/v0.8/ccip/pools/USDC/USDCTokenPool.sol 145
Total 3718

Issue Summary

Category No. of Issues
Critical 0
High 0
Medium 1
Low 4
NC 9

Medium Issues

M-1: Centralization Risk for trusted owners

Contracts have owners with privileged rights to perform admin tasks and need to be trusted to not perform malicious updates or drain funds.

  • Found in src/v0.8/ccip/ARM.sol Line: 259

       function ownerResetBlessVotes(IARM.TaggedRoot[] calldata taggedRoots) external onlyOwner {
  • Found in src/v0.8/ccip/ARM.sol Line: 341

       function ownerCurse() external onlyOwner {
  • Found in src/v0.8/ccip/ARM.sol Line: 352

       function ownerUnvoteToCurse(UnvoteToCurseRecord[] calldata unvoteRecords) external onlyOwner {
  • Found in src/v0.8/ccip/ARM.sol Line: 397

       function setConfig(Config memory config) external onlyOwner {
  • Found in src/v0.8/ccip/ARMProxy.sol Line: 31

       function setARM(address arm) public onlyOwner {
  • Found in src/v0.8/ccip/CommitStore.sol Line: 115

       function setMinSeqNr(uint64 minSeqNr) external onlyOwner {
  • Found in src/v0.8/ccip/CommitStore.sol Line: 127

       function setLatestPriceEpochAndRound(uint40 latestPriceEpochAndRound) external onlyOwner {
  • Found in src/v0.8/ccip/CommitStore.sol Line: 151

       function resetUnblessedRoots(bytes32[] calldata rootToReset) external onlyOwner {
  • Found in src/v0.8/ccip/CommitStore.sol Line: 303

       function pause() external onlyOwner {
  • Found in src/v0.8/ccip/CommitStore.sol Line: 310

       function unpause() external onlyOwner {
  • Found in src/v0.8/ccip/PriceRegistry.sol Line: 165

       ) external onlyOwner {
  • Found in src/v0.8/ccip/PriceRegistry.sol Line: 233

       ) external onlyOwner {
  • Found in src/v0.8/ccip/Router.sol Line: 199

       function setWrappedNative(address wrappedNative) external onlyOwner {
  • Found in src/v0.8/ccip/Router.sol Line: 239

       ) external onlyOwner {
  • Found in src/v0.8/ccip/Router.sol Line: 275

       function recoverTokens(address tokenAddress, address to, uint256 amount) external onlyOwner {
  • Found in src/v0.8/ccip/applications/CCIPClientExample.sol Line: 53

       function enableChain(uint64 chainSelector, bytes memory extraArgs) external onlyOwner {
  • Found in src/v0.8/ccip/applications/CCIPClientExample.sol Line: 57

       function disableChain(uint64 chainSelector) external onlyOwner {
  • Found in src/v0.8/ccip/applications/DefensiveExample.sol Line: 85

       function retryFailedMessage(bytes32 messageId, address tokenReceiver) external onlyOwner {
  • Found in src/v0.8/ccip/applications/DefensiveExample.sol Line: 103

       function setSimRevert(bool simRevert) external onlyOwner {
  • Found in src/v0.8/ccip/applications/PingPongDemo.sol Line: 37

       function setCounterpart(uint64 counterpartChainSelector, address counterpartAddress) external onlyOwner {
  • Found in src/v0.8/ccip/applications/PingPongDemo.sol Line: 42

       function startPingPong() external onlyOwner {
  • Found in src/v0.8/ccip/applications/PingPongDemo.sol Line: 79

       function setCounterpartChainSelector(uint64 chainSelector) external onlyOwner {
  • Found in src/v0.8/ccip/applications/PingPongDemo.sol Line: 91

       function setCounterpartAddress(address addr) external onlyOwner {
  • Found in src/v0.8/ccip/applications/PingPongDemo.sol Line: 99

       function setPaused(bool pause) external onlyOwner {
  • Found in src/v0.8/ccip/applications/SelfFundedPingPong.sol Line: 63

       function setCountIncrBeforeFunding(uint8 countIncrBeforeFunding) public onlyOwner {
  • Found in src/v0.8/ccip/ocr/OCR2Base.sol Line: 118

       ) external override checkConfigValid(signers.length, transmitters.length, f) onlyOwner {
  • Found in src/v0.8/ccip/ocr/OCR2BaseNoChecks.sol Line: 104

       ) external override checkConfigValid(transmitters.length, f) onlyOwner {
  • Found in src/v0.8/ccip/offRamp/EVM2EVMOffRamp.sol Line: 557

       ) external onlyOwner {
  • Found in src/v0.8/ccip/onRamp/EVM2EVMOnRamp.sol Line: 414

       function setDynamicConfig(DynamicConfig memory dynamicConfig) external onlyOwner {
  • Found in src/v0.8/ccip/onRamp/EVM2EVMOnRamp.sol Line: 463

       ) external onlyOwner {
  • Found in src/v0.8/ccip/pools/LockReleaseTokenPool.sol Line: 112

       function setRebalancer(address rebalancer) external onlyOwner {
  • Found in src/v0.8/ccip/pools/LockReleaseTokenPool.sol Line: 119

       function setRateLimitAdmin(address rateLimitAdmin) external onlyOwner {
  • Found in src/v0.8/ccip/pools/TokenPool.sol Line: 115

       function setRouter(address newRouter) public onlyOwner {
  • Found in src/v0.8/ccip/pools/TokenPool.sol Line: 155

       function applyChainUpdates(ChainUpdate[] calldata chains) external virtual onlyOwner {
  • Found in src/v0.8/ccip/pools/TokenPool.sol Line: 234

       ) external virtual onlyOwner {
  • Found in src/v0.8/ccip/pools/TokenPool.sol Line: 296

       function applyAllowListUpdates(address[] calldata removes, address[] calldata adds) external onlyOwner {
  • Found in src/v0.8/ccip/pools/USDC/USDCTokenPool.sol Line: 228

       function setDomains(DomainUpdate[] calldata domains) external onlyOwner {

Low Issues

L-1: ecrecover is susceptible to signature malleability

The ecrecover function is susceptible to signature malleability. This means that the same message can be signed in multiple ways, allowing an attacker to change the message signature without invalidating it. This can lead to unexpected behavior in smart contracts, such as the loss of funds or the ability to bypass access control. Consider using OpenZeppelin's ECDSA library instead of the built-in function.

  • Found in src/v0.8/ccip/ocr/OCR2Base.sol Line: 253

           address signer = ecrecover(h, uint8(rawVs[i]) + 27, rs[i], ss[i]);

L-2: Unsafe ERC20 Operations should not be used

ERC20 functions may not behave as expected. For example: return values are not always meaningful. It is recommended to use OpenZeppelin's SafeERC20 library.

  • Found in src/v0.8/ccip/applications/CCIPClientExample.sol Line: 50

         s_feeToken.approve(address(router), type(uint256).max);
  • Found in src/v0.8/ccip/applications/CCIPClientExample.sol Line: 123

           IERC20(tokenAmounts[i].token).transferFrom(msg.sender, address(this), tokenAmounts[i].amount);
  • Found in src/v0.8/ccip/applications/CCIPClientExample.sol Line: 124

           IERC20(tokenAmounts[i].token).approve(i_ccipRouter, tokenAmounts[i].amount);
  • Found in src/v0.8/ccip/applications/CCIPClientExample.sol Line: 148

           IERC20(tokenAmounts[i].token).transferFrom(msg.sender, address(this), tokenAmounts[i].amount);
  • Found in src/v0.8/ccip/applications/CCIPClientExample.sol Line: 149

           IERC20(tokenAmounts[i].token).approve(i_ccipRouter, tokenAmounts[i].amount);
  • Found in src/v0.8/ccip/applications/PingPongDemo.sol Line: 30

         s_feeToken.approve(address(router), type(uint256).max);
  • Found in src/v0.8/ccip/applications/TokenProxy.sol Line: 29

         IERC20(token).approve(router, type(uint256).max);
  • Found in src/v0.8/ccip/applications/TokenProxy.sol Line: 56

           IERC20(message.feeToken).approve(address(i_ccipRouter), feeAmount);
  • Found in src/v0.8/ccip/applications/TokenProxy.sol Line: 60

         IERC20(message.tokenAmounts[0].token).transferFrom(msg.sender, address(this), message.tokenAmounts[0].amount);

L-3: Solidity pragma should be specific, not wide

Consider using a specific version of Solidity in your contracts instead of a wide version. For example, instead of pragma solidity ^0.8.0;, use pragma solidity 0.8.0;

  • Found in src/v0.8/ccip/applications/CCIPClientExample.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/applications/CCIPReceiver.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/applications/DefensiveExample.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/applications/PingPongDemo.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/applications/SelfFundedPingPong.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/interfaces/IARM.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/interfaces/IAny2EVMMessageReceiver.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/interfaces/IAny2EVMOffRamp.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/interfaces/ICommitStore.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/interfaces/IEVM2AnyOnRamp.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/interfaces/IEVM2AnyOnRampClient.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/interfaces/IPriceRegistry.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/interfaces/IRouter.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/interfaces/IRouterClient.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/interfaces/IWrappedNative.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/interfaces/automation/ILinkAvailable.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/interfaces/pools/IPool.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/libraries/Client.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/libraries/Internal.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/libraries/MerkleMultiProof.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/libraries/RateLimiter.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/libraries/USDPriceWith18Decimals.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/ocr/OCR2Abstract.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/ocr/OCR2Base.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/ocr/OCR2BaseNoChecks.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/pools/USDC/IMessageTransmitter.sol Line: 16

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/pools/USDC/ITokenMessenger.sol Line: 16

     pragma solidity ^0.8.0;

L-4: PUSH0 is not supported by all chains

Solc compiler version 0.8.20 switches the default target EVM version to Shanghai, which means that the generated bytecode will include PUSH0 opcodes. Be sure to select the appropriate EVM version in case you intend to deploy on a chain other than mainnet like L2 chains that may not support PUSH0, otherwise deployment of your contracts will fail.

  • Found in src/v0.8/ccip/applications/CCIPClientExample.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/applications/CCIPReceiver.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/applications/DefensiveExample.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/applications/PingPongDemo.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/applications/SelfFundedPingPong.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/interfaces/IARM.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/interfaces/IAny2EVMMessageReceiver.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/interfaces/IAny2EVMOffRamp.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/interfaces/ICommitStore.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/interfaces/IEVM2AnyOnRamp.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/interfaces/IEVM2AnyOnRampClient.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/interfaces/IPriceRegistry.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/interfaces/IRouter.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/interfaces/IRouterClient.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/interfaces/IWrappedNative.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/interfaces/automation/ILinkAvailable.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/interfaces/pools/IPool.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/libraries/Client.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/libraries/Internal.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/libraries/MerkleMultiProof.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/libraries/RateLimiter.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/libraries/USDPriceWith18Decimals.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/ocr/OCR2Abstract.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/ocr/OCR2Base.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/ocr/OCR2BaseNoChecks.sol Line: 2

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/pools/USDC/IMessageTransmitter.sol Line: 16

     pragma solidity ^0.8.0;
  • Found in src/v0.8/ccip/pools/USDC/ITokenMessenger.sol Line: 16

     pragma solidity ^0.8.0;

NC Issues

NC-1: Missing checks for address(0) when assigning values to address state variables

Check for address(0) when assigning values to address state variables.

  • Found in src/v0.8/ccip/AggregateRateLimiter.sol Line: 84

         s_admin = newAdmin;
  • Found in src/v0.8/ccip/Router.sol Line: 69

         s_wrappedNative = wrappedNative;
  • Found in src/v0.8/ccip/Router.sol Line: 200

         s_wrappedNative = wrappedNative;
  • Found in src/v0.8/ccip/applications/CCIPClientExample.sol Line: 49

         s_feeToken = feeToken;
  • Found in src/v0.8/ccip/applications/PingPongDemo.sol Line: 29

         s_feeToken = feeToken;
  • Found in src/v0.8/ccip/applications/PingPongDemo.sol Line: 39

         s_counterpartAddress = counterpartAddress;
  • Found in src/v0.8/ccip/applications/PingPongDemo.sol Line: 92

         s_counterpartAddress = addr;
  • Found in src/v0.8/ccip/ocr/OCR2Base.sol Line: 140

         s_signers = signers;
  • Found in src/v0.8/ccip/ocr/OCR2Base.sol Line: 141

         s_transmitters = transmitters;
  • Found in src/v0.8/ccip/ocr/OCR2BaseNoChecks.sol Line: 119

         s_transmitters = transmitters;
  • Found in src/v0.8/ccip/pools/LockReleaseTokenPool.sol Line: 113

         s_rebalancer = rebalancer;
  • Found in src/v0.8/ccip/pools/LockReleaseTokenPool.sol Line: 120

         s_rateLimitAdmin = rateLimitAdmin;

NC-2: public functions not used internally could be marked external

Instead of marking a function as public, consider marking it as external if it is not used internally.

  • Found in src/v0.8/ccip/CommitStore.sol Line: 121

       function getLatestPriceEpochAndRound() public view returns (uint64) {
  • Found in src/v0.8/ccip/applications/CCIPReceiver.sol Line: 29

       function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) {
  • Found in src/v0.8/ccip/applications/SelfFundedPingPong.sol Line: 63

       function setCountIncrBeforeFunding(uint8 countIncrBeforeFunding) public onlyOwner {
  • Found in src/v0.8/ccip/offRamp/EVM2EVMOffRamp.sol Line: 204

       function getSenderNonce(address sender) public view returns (uint64 nonce) {
  • Found in src/v0.8/ccip/pools/LockReleaseTokenPool.sol Line: 92

       function getLockReleaseInterfaceId() public pure returns (bytes4) {
  • Found in src/v0.8/ccip/pools/LockReleaseTokenPool.sol Line: 97

       function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) {
  • Found in src/v0.8/ccip/pools/TokenPool.sol Line: 98

       function getArmProxy() public view returns (address armProxy) {
  • Found in src/v0.8/ccip/pools/TokenPool.sol Line: 109

       function getRouter() public view returns (address router) {
  • Found in src/v0.8/ccip/pools/TokenPool.sol Line: 115

       function setRouter(address newRouter) public onlyOwner {
  • Found in src/v0.8/ccip/pools/TokenPool.sol Line: 124

       function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) {
  • Found in src/v0.8/ccip/pools/TokenPool.sol Line: 140

       function getSupportedChains() public view returns (uint64[] memory) {
  • Found in src/v0.8/ccip/pools/USDC/USDCTokenPool.sol Line: 99

       function getUSDCInterfaceId() public pure returns (bytes4) {
  • Found in src/v0.8/ccip/pools/USDC/USDCTokenPool.sol Line: 104

       function supportsInterface(bytes4 interfaceId) public pure override returns (bool) {

NC-3: Define and use constant variables instead of using literals

If the same constant literal value is used multiple times, create a constant state variable and reference it throughout the contract.

  • Found in src/v0.8/ccip/ARM.sol Line: 494

         address[] memory allAddrs = new address[](3 * config.voters.length);
  • Found in src/v0.8/ccip/ARM.sol Line: 505

           allAddrs[3 * i + 0] = voter.blessVoteAddr;
  • Found in src/v0.8/ccip/ARM.sol Line: 506

           allAddrs[3 * i + 1] = voter.curseVoteAddr;
  • Found in src/v0.8/ccip/ARM.sol Line: 507

           allAddrs[3 * i + 2] = voter.curseUnvoteAddr;
  • Found in src/v0.8/ccip/Router.sol Line: 184

         return (uint256(sourceChainSelector) << 160) + uint160(offRampAddress);
  • Found in src/v0.8/ccip/Router.sol Line: 220

             sourceChainSelector: uint64(encodedOffRamp >> 160),
  • Found in src/v0.8/ccip/libraries/USDPriceWith18Decimals.sol Line: 24

         return (tokenPrice * tokenAmount) / 1e18;
  • Found in src/v0.8/ccip/libraries/USDPriceWith18Decimals.sol Line: 43

         return (usdValue * 1e18) / tokenPrice;
  • Found in src/v0.8/ccip/ocr/OCR2Abstract.sol Line: 84

         uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00
  • Found in src/v0.8/ccip/ocr/OCR2Abstract.sol Line: 85

         uint256 prefix = 0x0001 << (256 - 16); // 0x000100..00
  • Found in src/v0.8/ccip/ocr/OCR2Base.sol Line: 100

         if (numSigners <= 3 * f) revert InvalidConfig("faulty-oracle f too high");
  • Found in src/v0.8/ccip/ocr/OCR2Base.sol Line: 191

         bytes32[3] calldata reportContext,
  • Found in src/v0.8/ccip/ocr/OCR2Base.sol Line: 240

             32 + // 32 bytes per entry in _rs
  • Found in src/v0.8/ccip/ocr/OCR2Base.sol Line: 242

             32; // 32 bytes per entry in _ss)
  • Found in src/v0.8/ccip/ocr/OCR2BaseNoChecks.sol Line: 201

           32 + // 32 bytes per entry in _rs
  • Found in src/v0.8/ccip/ocr/OCR2BaseNoChecks.sol Line: 203

           32; // 32 bytes per entry in _ss)
  • Found in src/v0.8/ccip/offRamp/EVM2EVMOffRamp.sol Line: 182

             (s_executionStates[sequenceNumber / 128] >> ((sequenceNumber % 128) * MESSAGE_EXECUTION_STATE_BIT_WIDTH)) &
  • Found in src/v0.8/ccip/offRamp/EVM2EVMOffRamp.sol Line: 192

         uint256 offset = (sequenceNumber % 128) * MESSAGE_EXECUTION_STATE_BIT_WIDTH;
  • Found in src/v0.8/ccip/offRamp/EVM2EVMOffRamp.sol Line: 193

         uint256 bitmap = s_executionStates[sequenceNumber / 128];
  • Found in src/v0.8/ccip/offRamp/EVM2EVMOffRamp.sol Line: 200

         s_executionStates[sequenceNumber / 128] = bitmap;
  • Found in src/v0.8/ccip/onRamp/EVM2EVMOnRamp.sol Line: 536

           premiumFee = uint256(feeTokenConfig.networkFeeUSDCents) * 1e16;
  • Found in src/v0.8/ccip/onRamp/EVM2EVMOnRamp.sol Line: 653

           uint256 minFeeUSDWei = uint256(transferFeeConfig.minFeeUSDCents) * 1e16;
  • Found in src/v0.8/ccip/onRamp/EVM2EVMOnRamp.sol Line: 659

           uint256 maxFeeUSDWei = uint256(transferFeeConfig.maxFeeUSDCents) * 1e16;

NC-4: Event is missing indexed fields

Index event fields make the field more quickly accessible to off-chain tools that parse events. However, note that each index field costs extra gas during emission, so it's not necessarily best to index the maximum allowed per event (three fields). Each event should use three indexed fields if there are three or more fields, and gas usage is not particularly of concern for the events in question. If there are fewer than three fields, all of the fields should be indexed.

  • Found in src/v0.8/ccip/ARM.sol Line: 118

       event ConfigSet(uint32 indexed configVersion, Config config);
  • Found in src/v0.8/ccip/ARM.sol Line: 122

       event TaggedRootBlessed(uint32 indexed configVersion, IARM.TaggedRoot taggedRoot, uint16 accumulatedWeight);
  • Found in src/v0.8/ccip/ARM.sol Line: 123

       event TaggedRootBlessVotesReset(uint32 indexed configVersion, IARM.TaggedRoot taggedRoot, bool wasBlessed);
  • Found in src/v0.8/ccip/ARM.sol Line: 124

       event VotedToBless(uint32 indexed configVersion, address indexed voter, IARM.TaggedRoot taggedRoot, uint8 weight);
  • Found in src/v0.8/ccip/ARM.sol Line: 126

       event VotedToCurse(
  • Found in src/v0.8/ccip/ARM.sol Line: 135

       event ReusedVotesToCurse(
  • Found in src/v0.8/ccip/ARM.sol Line: 143

       event UnvotedToCurse(
  • Found in src/v0.8/ccip/ARM.sol Line: 150

       event SkippedUnvoteToCurse(address indexed voter, bytes32 expectedCursesHash, bytes32 actualCursesHash);
  • Found in src/v0.8/ccip/ARM.sol Line: 151

       event OwnerCursed(uint256 timestamp);
  • Found in src/v0.8/ccip/ARM.sol Line: 152

       event Cursed(uint32 indexed configVersion, uint256 timestamp);
  • Found in src/v0.8/ccip/ARM.sol Line: 156

       event AlreadyVotedToBless(uint32 indexed configVersion, address indexed voter, IARM.TaggedRoot taggedRoot);
  • Found in src/v0.8/ccip/ARM.sol Line: 157

       event AlreadyBlessed(uint32 indexed configVersion, address indexed voter, IARM.TaggedRoot taggedRoot);
  • Found in src/v0.8/ccip/ARMProxy.sol Line: 16

       event ARMSet(address arm);
  • Found in src/v0.8/ccip/AggregateRateLimiter.sol Line: 20

       event AdminSet(address newAdmin);
  • Found in src/v0.8/ccip/CommitStore.sol Line: 22

       event Paused(address account);
  • Found in src/v0.8/ccip/CommitStore.sol Line: 23

       event Unpaused(address account);
  • Found in src/v0.8/ccip/CommitStore.sol Line: 25

       event ReportAccepted(CommitReport report);
  • Found in src/v0.8/ccip/CommitStore.sol Line: 26

       event ConfigSet(StaticConfig staticConfig, DynamicConfig dynamicConfig);
  • Found in src/v0.8/ccip/CommitStore.sol Line: 27

       event RootRemoved(bytes32 root);
  • Found in src/v0.8/ccip/PriceRegistry.sol Line: 30

       event UsdPerUnitGasUpdated(uint64 indexed destChain, uint256 value, uint256 timestamp);
  • Found in src/v0.8/ccip/PriceRegistry.sol Line: 31

       event UsdPerTokenUpdated(address indexed token, uint256 value, uint256 timestamp);
  • Found in src/v0.8/ccip/Router.sol Line: 33

       event OnRampSet(uint64 indexed destChainSelector, address onRamp);
  • Found in src/v0.8/ccip/Router.sol Line: 34

       event OffRampAdded(uint64 indexed sourceChainSelector, address offRamp);
  • Found in src/v0.8/ccip/Router.sol Line: 35

       event OffRampRemoved(uint64 indexed sourceChainSelector, address offRamp);
  • Found in src/v0.8/ccip/Router.sol Line: 36

       event MessageExecuted(bytes32 messageId, uint64 sourceChainSelector, address offRamp, bytes32 calldataHash);
  • Found in src/v0.8/ccip/applications/CCIPClientExample.sol Line: 29

       event MessageSent(bytes32 messageId);
  • Found in src/v0.8/ccip/applications/CCIPClientExample.sol Line: 30

       event MessageReceived(bytes32 messageId);
  • Found in src/v0.8/ccip/applications/DefensiveExample.sol Line: 21

       event MessageFailed(bytes32 indexed messageId, bytes reason);
  • Found in src/v0.8/ccip/applications/PingPongDemo.sol Line: 15

       event Ping(uint256 pingPongCount);
  • Found in src/v0.8/ccip/applications/PingPongDemo.sol Line: 16

       event Pong(uint256 pingPongCount);
  • Found in src/v0.8/ccip/applications/SelfFundedPingPong.sol Line: 15

       event CountIncrBeforeFundingSet(uint8 countIncrBeforeFunding);
  • Found in src/v0.8/ccip/libraries/RateLimiter.sol Line: 22

       event TokensConsumed(uint256 tokens);
  • Found in src/v0.8/ccip/libraries/RateLimiter.sol Line: 23

       event ConfigChanged(Config config);
  • Found in src/v0.8/ccip/ocr/OCR2Abstract.sol Line: 20

       event ConfigSet(
  • Found in src/v0.8/ccip/ocr/OCR2Abstract.sol Line: 92

       event Transmitted(bytes32 configDigest, uint32 epoch);
  • Found in src/v0.8/ccip/offRamp/EVM2EVMOffRamp.sol Line: 62

       event PoolAdded(address token, address pool);
  • Found in src/v0.8/ccip/offRamp/EVM2EVMOffRamp.sol Line: 63

       event PoolRemoved(address token, address pool);
  • Found in src/v0.8/ccip/offRamp/EVM2EVMOffRamp.sol Line: 65

       event ConfigSet(StaticConfig staticConfig, DynamicConfig dynamicConfig);
  • Found in src/v0.8/ccip/offRamp/EVM2EVMOffRamp.sol Line: 69

       event ExecutionStateChanged(
  • Found in src/v0.8/ccip/onRamp/EVM2EVMOnRamp.sol Line: 62

       event ConfigSet(StaticConfig staticConfig, DynamicConfig dynamicConfig);
  • Found in src/v0.8/ccip/onRamp/EVM2EVMOnRamp.sol Line: 63

       event NopPaid(address indexed nop, uint256 amount);
  • Found in src/v0.8/ccip/onRamp/EVM2EVMOnRamp.sol Line: 64

       event FeeConfigSet(FeeTokenConfigArgs[] feeConfig);
  • Found in src/v0.8/ccip/onRamp/EVM2EVMOnRamp.sol Line: 65

       event TokenTransferFeeConfigSet(TokenTransferFeeConfigArgs[] transferFeeConfig);
  • Found in src/v0.8/ccip/onRamp/EVM2EVMOnRamp.sol Line: 67

       event CCIPSendRequested(Internal.EVM2EVMMessage message);
  • Found in src/v0.8/ccip/onRamp/EVM2EVMOnRamp.sol Line: 68

       event NopsSet(uint256 nopWeightsTotal, NopAndWeight[] nopsAndWeights);
  • Found in src/v0.8/ccip/onRamp/EVM2EVMOnRamp.sol Line: 69

       event PoolAdded(address token, address pool);
  • Found in src/v0.8/ccip/onRamp/EVM2EVMOnRamp.sol Line: 70

       event PoolRemoved(address token, address pool);
  • Found in src/v0.8/ccip/pools/TokenPool.sol Line: 32

       event Locked(address indexed sender, uint256 amount);
  • Found in src/v0.8/ccip/pools/TokenPool.sol Line: 33

       event Burned(address indexed sender, uint256 amount);
  • Found in src/v0.8/ccip/pools/TokenPool.sol Line: 34

       event Released(address indexed sender, address indexed recipient, uint256 amount);
  • Found in src/v0.8/ccip/pools/TokenPool.sol Line: 35

       event Minted(address indexed sender, address indexed recipient, uint256 amount);
  • Found in src/v0.8/ccip/pools/TokenPool.sol Line: 36

       event ChainAdded(
  • Found in src/v0.8/ccip/pools/TokenPool.sol Line: 41

       event ChainConfigured(
  • Found in src/v0.8/ccip/pools/TokenPool.sol Line: 46

       event ChainRemoved(uint64 remoteChainSelector);
  • Found in src/v0.8/ccip/pools/TokenPool.sol Line: 47

       event AllowListAdd(address sender);
  • Found in src/v0.8/ccip/pools/TokenPool.sol Line: 48

       event AllowListRemove(address sender);
  • Found in src/v0.8/ccip/pools/TokenPool.sol Line: 49

       event RouterUpdated(address oldRouter, address newRouter);
  • Found in src/v0.8/ccip/pools/USDC/USDCTokenPool.sol Line: 19

       event DomainsSet(DomainUpdate[]);
  • Found in src/v0.8/ccip/pools/USDC/USDCTokenPool.sol Line: 20

       event ConfigSet(address tokenMessenger);

NC-5: Empty require() / revert() statements

Use descriptive reason strings or custom errors for revert paths.

  • Found in src/v0.8/ccip/offRamp/EVM2EVMOffRamp.sol Line: 645

         revert();

NC-6: Modifiers invoked only once can be shoe-horned into the function

  • Found in src/v0.8/ccip/CommitStore.sol Line: 285

       modifier whenHealthy() {
  • Found in src/v0.8/ccip/PriceRegistry.sol Line: 259

       modifier requireUpdaterOrOwner() {
  • Found in src/v0.8/ccip/applications/DefensiveExample.sol Line: 107

       modifier onlySelf() {
  • Found in src/v0.8/ccip/ocr/OCR2Base.sol Line: 92

       modifier checkConfigValid(
  • Found in src/v0.8/ccip/ocr/OCR2BaseNoChecks.sol Line: 80

       modifier checkConfigValid(uint256 numTransmitters, uint256 f) {
  • Found in src/v0.8/ccip/offRamp/EVM2EVMOffRamp.sol Line: 650

       modifier whenHealthy() {
  • Found in src/v0.8/ccip/onRamp/EVM2EVMOnRamp.sol Line: 869

       modifier onlyOwnerOrAdminOrNop() {
  • Found in src/v0.8/ccip/onRamp/EVM2EVMOnRamp.sol Line: 882

       modifier whenHealthy() {

NC-7: Empty Block

Consider removing empty blocks.

  • Found in src/v0.8/ccip/ocr/OCR2Base.sol Line: 175

       function _beforeSetConfig(bytes memory _onchainConfig) internal virtual {}
  • Found in src/v0.8/ccip/ocr/OCR2BaseNoChecks.sol Line: 153

       function _beforeSetConfig(bytes memory _onchainConfig) internal virtual {}

NC-8: Large literal values multiples of 10000 can be replaced with scientific notation

Use e notation, for example: 1e18, instead of its full numeric value.

  • Found in src/v0.8/ccip/libraries/MerkleMultiProof.sol Line: 6

       bytes32 internal constant LEAF_DOMAIN_SEPARATOR = 0x0000000000000000000000000000000000000000000000000000000000000000;

NC-9: Internal functions called only once can be inlined

Instead of separating the logic into a separate function, consider inlining the logic into the calling function. This can reduce the number of function calls and improve readability.

  • Found in src/v0.8/ccip/ARM.sol Line: 183

       function _bitmapSet(uint128 bitmap, uint8 index) internal pure returns (uint128) {
  • Found in src/v0.8/ccip/ARM.sol Line: 188

       function _bitmapCount(uint128 bitmap) internal pure returns (uint8 oneBits) {
  • Found in src/v0.8/ccip/ARM.sol Line: 482

       function _validateConfig(Config memory config) internal pure returns (bool) {
  • Found in src/v0.8/ccip/applications/CCIPClientExample.sol Line: 70

       function _ccipReceive(Client.Any2EVMMessage memory message) internal override {
  • Found in src/v0.8/ccip/applications/CCIPReceiver.sol Line: 40

       function _ccipReceive(Client.Any2EVMMessage memory message) internal virtual;
  • Found in src/v0.8/ccip/ocr/OCR2Base.sol Line: 175

       function _beforeSetConfig(bytes memory _onchainConfig) internal virtual {}
  • Found in src/v0.8/ccip/ocr/OCR2Base.sol Line: 287

       function _report(bytes calldata report, uint40 epochAndRound) internal virtual;
  • Found in src/v0.8/ccip/ocr/OCR2BaseNoChecks.sol Line: 153

       function _beforeSetConfig(bytes memory _onchainConfig) internal virtual {}
  • Found in src/v0.8/ccip/ocr/OCR2BaseNoChecks.sol Line: 231

       function _report(bytes calldata report) internal virtual;
  • Found in src/v0.8/ccip/offRamp/EVM2EVMOffRamp.sol Line: 396

       function _trialExecute(
  • Found in src/v0.8/ccip/offRamp/EVM2EVMOffRamp.sol Line: 450

       function _metadataHash(bytes32 prefix) internal view returns (bytes32) {
  • Found in src/v0.8/ccip/offRamp/EVM2EVMOffRamp.sol Line: 598

       function _releaseOrMintTokens(
  • Found in src/v0.8/ccip/onRamp/EVM2EVMOnRamp.sol Line: 581

       function _getDataAvailabilityCost(
  • Found in src/v0.8/ccip/onRamp/EVM2EVMOnRamp.sol Line: 618

       function _getTokenTransferCost(
  • Found in src/v0.8/ccip/pools/BurnMintTokenPoolAbstract.sol Line: 12

       function _burn(uint256 amount) internal virtual;
  • Found in src/v0.8/ccip/pools/USDC/USDCTokenPool.sol Line: 186

       function _validateMessage(bytes memory usdcMessage, SourceTokenDataPayload memory sourceTokenData) internal view {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment