From dd6d04e407e186e13628cec5552359a30082b527 Mon Sep 17 00:00:00 2001 From: Josh Date: Tue, 24 Dec 2024 11:40:40 -0500 Subject: [PATCH] Initial Scaffolding Tests still needed --- contracts/.changeset/clean-horses-cheat.md | 5 + contracts/gas-snapshots/ccip.gas-snapshot | 126 +++++++++--------- contracts/src/v0.8/ccip/FeeQuoter.sol | 61 ++++++++- contracts/src/v0.8/ccip/libraries/Client.sol | 13 ++ .../src/v0.8/ccip/libraries/Internal.sol | 11 ++ .../feeQuoter/FeeQuoter.getValidatedFee.t.sol | 18 +++ 6 files changed, 167 insertions(+), 67 deletions(-) create mode 100644 contracts/.changeset/clean-horses-cheat.md diff --git a/contracts/.changeset/clean-horses-cheat.md b/contracts/.changeset/clean-horses-cheat.md new file mode 100644 index 00000000000..a46655a3c61 --- /dev/null +++ b/contracts/.changeset/clean-horses-cheat.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': minor +--- + +Update FeeQuoter to support Solana chain families #feature diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 0c81de75a01..96f48bf0aac 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -10,7 +10,7 @@ BurnMintTokenPool_releaseOrMint:test_PoolMint() (gas: 102527) BurnMintWithLockReleaseFlagTokenPool_lockOrBurn:test_LockOrBurn_CorrectReturnData() (gas: 237292) BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn() (gas: 239012) BurnWithFromMintTokenPool_lockOrBurn:test_Setup() (gas: 24169) -CCIPClientExample_sanity:test_ImmutableExamples() (gas: 2072849) +CCIPClientExample_sanity:test_ImmutableExamples() (gas: 2073842) CCIPHome__validateConfig:test__validateConfig() (gas: 300016) CCIPHome__validateConfig:test__validateConfigLessTransmittersThanSigners() (gas: 332965) CCIPHome__validateConfig:test__validateConfigSmallerFChain() (gas: 459322) @@ -28,7 +28,7 @@ CCIPHome_setCandidate:test_setCandidate() (gas: 1365392) CCIPHome_supportsInterface:test_supportsInterface() (gas: 9885) DefensiveExampleTest:test_HappyPath() (gas: 200517) DefensiveExampleTest:test_Recovery() (gas: 424996) -E2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1490237) +E2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1491182) ERC165CheckerReverting_supportsInterfaceReverting:test__supportsInterfaceReverting() (gas: 10445) EtherSenderReceiverTest_ccipReceive:test_ccipReceive_fallbackToWethTransfer() (gas: 96964) EtherSenderReceiverTest_ccipReceive:test_ccipReceive_happyPath() (gas: 49797) @@ -63,22 +63,22 @@ FactoryBurnMintERC20_increaseApproval:test_IncreaseApproval() (gas: 44421) FactoryBurnMintERC20_mint:test_BasicMint() (gas: 149826) FactoryBurnMintERC20_supportsInterface:test_SupportsInterface() (gas: 11539) FactoryBurnMintERC20_transfer:test_Transfer() (gas: 42505) -FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates() (gas: 141541) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates() (gas: 141871) FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroInput() (gas: 12536) FeeQuoter_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates() (gas: 162691) FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens() (gas: 54793) FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken() (gas: 45276) FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12380) -FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig() (gas: 88736) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig() (gas: 88688) FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13218) -FeeQuoter_constructor:test_Setup() (gas: 5039899) +FeeQuoter_constructor:test_Setup() (gas: 5254478) FeeQuoter_convertTokenAmount:test_ConvertTokenAmount() (gas: 68417) -FeeQuoter_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost() (gas: 96377) -FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost() (gas: 21075) -FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector() (gas: 14836) +FeeQuoter_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost() (gas: 96540) +FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost() (gas: 21074) +FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector() (gas: 14835) FeeQuoter_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices() (gas: 73123) -FeeQuoter_getTokenAndGasPrices:test_StalenessCheckDisabled() (gas: 111926) -FeeQuoter_getTokenAndGasPrices:test_ZeroGasPrice() (gas: 109013) +FeeQuoter_getTokenAndGasPrices:test_StalenessCheckDisabled() (gas: 112091) +FeeQuoter_getTokenAndGasPrices:test_ZeroGasPrice() (gas: 109178) FeeQuoter_getTokenPrice:test_GetTokenPriceFromFeed() (gas: 68180) FeeQuoter_getTokenPrice:test_GetTokenPrice_LocalMoreRecent() (gas: 33568) FeeQuoter_getTokenPrices:test_GetTokenPrices() (gas: 78534) @@ -89,13 +89,13 @@ FeeQuoter_getTokenTransferCost:test_MixedTokenTransferFee() (gas: 96077) FeeQuoter_getTokenTransferCost:test_NoTokenTransferChargesZeroFee() (gas: 20587) FeeQuoter_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas() (gas: 27978) FeeQuoter_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas() (gas: 27979) -FeeQuoter_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee() (gas: 40537) +FeeQuoter_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee() (gas: 40513) FeeQuoter_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults() (gas: 29706) -FeeQuoter_getValidatedFee:test_EmptyMessage() (gas: 83608) -FeeQuoter_getValidatedFee:test_HighGasMessage() (gas: 240058) -FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer() (gas: 143671) -FeeQuoter_getValidatedFee:test_SingleTokenMessage() (gas: 115178) -FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier() (gas: 63919) +FeeQuoter_getValidatedFee:test_EmptyMessage() (gas: 83948) +FeeQuoter_getValidatedFee:test_HighGasMessage() (gas: 240398) +FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer() (gas: 144011) +FeeQuoter_getValidatedFee:test_SingleTokenMessage() (gas: 115518) +FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier() (gas: 64255) FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPrice() (gas: 58905) FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed() (gas: 65115) FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals() (gas: 1897724) @@ -106,18 +106,18 @@ FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecim FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value() (gas: 1897534) FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod() (gas: 65233) FeeQuoter_getValidatedTokenPrice:test_StaleFeeToken() (gas: 61854) -FeeQuoter_onReport:test_OnReport_SkipPriceUpdateWhenStaleUpdateReceived() (gas: 52631) -FeeQuoter_onReport:test_onReport() (gas: 89096) -FeeQuoter_onReport:test_onReport_withKeystoneForwarderContract() (gas: 122724) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsDefault() (gas: 17207) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV1() (gas: 18283) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV2() (gas: 18391) -FeeQuoter_processMessageArgs:test_processMessageArgs_WitEVMExtraArgsV2() (gas: 28669) -FeeQuoter_processMessageArgs:test_processMessageArgs_WithConvertedTokenAmount() (gas: 30001) -FeeQuoter_processMessageArgs:test_processMessageArgs_WithCorrectPoolReturnData() (gas: 76624) -FeeQuoter_processMessageArgs:test_processMessageArgs_WithEVMExtraArgsV1() (gas: 28300) -FeeQuoter_processMessageArgs:test_processMessageArgs_WithEmptyEVMExtraArgs() (gas: 26158) -FeeQuoter_processMessageArgs:test_processMessageArgs_WithLinkTokenAmount() (gas: 19641) +FeeQuoter_onReport:test_OnReport_SkipPriceUpdateWhenStaleUpdateReceived() (gas: 52619) +FeeQuoter_onReport:test_onReport() (gas: 89084) +FeeQuoter_onReport:test_onReport_withKeystoneForwarderContract() (gas: 122712) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsDefault() (gas: 17439) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV1() (gas: 18515) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV2() (gas: 18623) +FeeQuoter_processMessageArgs:test_processMessageArgs_WitEVMExtraArgsV2() (gas: 28667) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithConvertedTokenAmount() (gas: 29999) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithCorrectPoolReturnData() (gas: 76768) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithEVMExtraArgsV1() (gas: 28298) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithEmptyEVMExtraArgs() (gas: 26156) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithLinkTokenAmount() (gas: 19639) FeeQuoter_supportsInterface:test_SupportsInterface() (gas: 13264) FeeQuoter_updatePrices:test_OnlyGasPrice() (gas: 23912) FeeQuoter_updatePrices:test_OnlyTokenPrice() (gas: 28761) @@ -128,8 +128,8 @@ FeeQuoter_updateTokenPriceFeeds:test_FeedUnset() (gas: 66506) FeeQuoter_updateTokenPriceFeeds:test_MultipleFeedUpdate() (gas: 93647) FeeQuoter_updateTokenPriceFeeds:test_SingleFeedUpdate() (gas: 53215) FeeQuoter_updateTokenPriceFeeds:test_ZeroFeeds() (gas: 12471) -FeeQuoter_validateDestFamilyAddress:test_ValidEVMAddress() (gas: 6789) -FeeQuoter_validateDestFamilyAddress:test_ValidNonEVMAddress() (gas: 6514) +FeeQuoter_validateDestFamilyAddress:test_ValidEVMAddress() (gas: 6872) +FeeQuoter_validateDestFamilyAddress:test_ValidNonEVMAddress() (gas: 6596) HybridLockReleaseUSDCTokenPool_TransferLiquidity:test_transferLiquidity() (gas: 167013) HybridLockReleaseUSDCTokenPool_lockOrBurn:test_PrimaryMechanism() (gas: 130356) HybridLockReleaseUSDCTokenPool_lockOrBurn:test_onLockReleaseMechanism() (gas: 140104) @@ -206,10 +206,10 @@ NonceManager_getIncrementedOutboundNonce:test_getIncrementedOutboundNonce() (gas NonceManager_getIncrementedOutboundNonce:test_incrementInboundNonce() (gas: 38746) NonceManager_getIncrementedOutboundNonce:test_incrementInboundNonce_SkippedIncorrectNonce() (gas: 23739) NonceManager_getIncrementedOutboundNonce:test_incrementNoncesInboundAndOutbound() (gas: 71886) -NonceManager_getOutboundNonce:test_getOutboundNonce_Upgrade() (gas: 105254) -NonceManager_getOutboundNonce:test_getOutboundNonce_UpgradeNonceNewSenderStartsAtZero() (gas: 166086) -NonceManager_getOutboundNonce:test_getOutboundNonce_UpgradeNonceStartsAtV1Nonce() (gas: 195806) -NonceManager_getOutboundNonce:test_getOutboundNonce_UpgradeSenderNoncesReadsPreviousRamp() (gas: 140101) +NonceManager_getOutboundNonce:test_getOutboundNonce_Upgrade() (gas: 105252) +NonceManager_getOutboundNonce:test_getOutboundNonce_UpgradeNonceNewSenderStartsAtZero() (gas: 166082) +NonceManager_getOutboundNonce:test_getOutboundNonce_UpgradeNonceStartsAtV1Nonce() (gas: 195800) +NonceManager_getOutboundNonce:test_getOutboundNonce_UpgradeSenderNoncesReadsPreviousRamp() (gas: 140095) OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains() (gas: 626140) OffRamp_applySourceChainConfigUpdates:test_AddNewChain() (gas: 166441) OffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates() (gas: 16671) @@ -275,33 +275,33 @@ OffRamp_trialExecute:test_trialExecute() (gas: 263635) OffRamp_trialExecute:test_trialExecute_RateLimitError() (gas: 120721) OffRamp_trialExecute:test_trialExecute_TokenHandlingErrorIsCaught() (gas: 132031) OffRamp_trialExecute:test_trialExecute_TokenPoolIsNotAContract() (gas: 281380) -OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy() (gas: 244294) +OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy() (gas: 244807) OnRamp_applyAllowlistUpdates:test_applyAllowlistUpdates() (gas: 325979) OnRamp_applyAllowlistUpdates:test_applyAllowlistUpdates_InvalidAllowListRequestDisabledAllowListWithAdds() (gas: 17190) OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates() (gas: 65874) OnRamp_constructor:test_Constructor() (gas: 2672129) -OnRamp_forwardFromRouter:test_ForwardFromRouter() (gas: 145362) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2() (gas: 146196) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue() (gas: 115375) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145760) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 144036) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 146001) -OnRamp_forwardFromRouter:test_ForwardFromRouter_ConfigurableSourceRouter() (gas: 140639) -OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered() (gas: 186473) -OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce() (gas: 212828) -OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 147007) -OnRamp_forwardFromRouter:test_forwardFromRouter_WithInterception() (gas: 274726) -OnRamp_getFee:test_EmptyMessage() (gas: 99005) -OnRamp_getFee:test_GetFeeOfZeroForTokenMessage() (gas: 86961) -OnRamp_getFee:test_SingleTokenMessage() (gas: 114125) +OnRamp_forwardFromRouter:test_ForwardFromRouter() (gas: 145360) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2() (gas: 146194) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue() (gas: 115373) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145758) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 144034) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 145999) +OnRamp_forwardFromRouter:test_ForwardFromRouter_ConfigurableSourceRouter() (gas: 140637) +OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered() (gas: 186467) +OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce() (gas: 212822) +OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 147005) +OnRamp_forwardFromRouter:test_forwardFromRouter_WithInterception() (gas: 274797) +OnRamp_getFee:test_EmptyMessage() (gas: 99689) +OnRamp_getFee:test_GetFeeOfZeroForTokenMessage() (gas: 87468) +OnRamp_getFee:test_SingleTokenMessage() (gas: 114809) OnRamp_getTokenPool:test_GetTokenPool() (gas: 35382) OnRamp_setDynamicConfig:test_setDynamicConfig() (gas: 56650) OnRamp_withdrawFeeTokens:test_WithdrawFeeTokens() (gas: 125835) -PingPong_ccipReceive:test_CcipReceive() (gas: 165845) +PingPong_ccipReceive:test_CcipReceive() (gas: 166014) PingPong_setOutOfOrderExecution:test_OutOfOrderExecution() (gas: 20350) PingPong_setPaused:test_Pausing() (gas: 17738) -PingPong_startPingPong:test_StartPingPong_With_OOO() (gas: 144996) -PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered() (gas: 170649) +PingPong_startPingPong:test_StartPingPong_With_OOO() (gas: 145165) +PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered() (gas: 170818) RMNHome_getConfigDigests:test_getConfigDigests() (gas: 1081176) RMNHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive() (gas: 1086556) RMNHome_revokeCandidate:test_revokeCandidate() (gas: 28085) @@ -327,20 +327,20 @@ RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin:test_registerAdminViaGetC RegistryModuleOwnerCustom_registerAdminViaOwner:test_registerAdminViaOwner() (gas: 129941) Router_applyRampUpdates:test_applyRampUpdates_OffRampUpdatesWithRouting() (gas: 10413055) Router_applyRampUpdates:test_applyRampUpdates_OnRampDisable() (gas: 56445) -Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 124459) -Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 211890) +Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 124628) +Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 212132) Router_ccipSend:test_InvalidMsgValue() (gas: 27856) -Router_ccipSend:test_NativeFeeToken() (gas: 184996) -Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 62458) -Router_ccipSend:test_NativeFeeTokenOverpay() (gas: 186413) -Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 54550) -Router_ccipSend:test_NonLinkFeeToken() (gas: 219583) -Router_ccipSend:test_WrappedNativeFeeToken() (gas: 187235) -Router_ccipSend:test_ccipSend_nativeFeeNoTokenSuccess_gas() (gas: 133616) -Router_ccipSend:test_ccipSend_nativeFeeOneTokenSuccess_gas() (gas: 221091) +Router_ccipSend:test_NativeFeeToken() (gas: 185336) +Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 62629) +Router_ccipSend:test_NativeFeeTokenOverpay() (gas: 186753) +Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 54721) +Router_ccipSend:test_NonLinkFeeToken() (gas: 219752) +Router_ccipSend:test_WrappedNativeFeeToken() (gas: 187575) +Router_ccipSend:test_ccipSend_nativeFeeNoTokenSuccess_gas() (gas: 133785) +Router_ccipSend:test_ccipSend_nativeFeeOneTokenSuccess_gas() (gas: 221333) Router_constructor:test_Constructor() (gas: 13148) Router_getArmProxy:test_getArmProxy() (gas: 10573) -Router_getFee:test_GetFeeSupportedChain() (gas: 52021) +Router_getFee:test_GetFeeSupportedChain() (gas: 52192) Router_recoverTokens:test_RecoverTokens() (gas: 52668) Router_routeMessage:test_routeMessage_AutoExec() (gas: 38071) Router_routeMessage:test_routeMessage_ExecutionEvent() (gas: 153593) diff --git a/contracts/src/v0.8/ccip/FeeQuoter.sol b/contracts/src/v0.8/ccip/FeeQuoter.sol index 8275999af9e..9920fcb7db3 100644 --- a/contracts/src/v0.8/ccip/FeeQuoter.sol +++ b/contracts/src/v0.8/ccip/FeeQuoter.sol @@ -44,6 +44,7 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, error MessageTooLarge(uint256 maxSize, uint256 actualSize); error UnsupportedNumberOfTokens(uint256 numberOfTokens, uint256 maxNumberOfTokensPerMsg); error InvalidFeeRange(uint256 minFeeUSDCents, uint256 maxFeeUSDCents); + error SolAddressCannotBeWritable(bytes SolAddress); event FeeTokenAdded(address indexed feeToken); event FeeTokenRemoved(address indexed feeToken); @@ -602,7 +603,7 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, * ( destChainConfig.destGasOverhead + ((message.data.length + tokenTransferBytesOverhead) * destChainConfig.destGasPerPayloadByte) + tokenTransferGas - + _parseEVMExtraArgsFromBytes(message.extraArgs, destChainConfig).gasLimit + + _parseGasLimitFromExtraArgBytes(message.extraArgs, destChainConfig) ) * destChainConfig.gasMultiplierWeiPerEth; // Calculate number of fee tokens to charge. @@ -852,6 +853,61 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, if (chainFamilySelector == Internal.CHAIN_FAMILY_SELECTOR_EVM) { Internal._validateEVMAddress(destAddress); } + + if (chainFamilySelector == Internal.CHAIN_FAMILY_SELECTOR_SOL) { + Internal._validateSolAddress(destAddress); + } + } + + function _parseGasLimitFromExtraArgBytes( + bytes calldata extraArgs, + DestChainConfig memory destChainConfig + ) internal pure returns (uint256 gasLimit) { + if (destChainConfig.chainFamilySelector == Internal.CHAIN_FAMILY_SELECTOR_EVM) { + return _parseEVMExtraArgsFromBytes(extraArgs, destChainConfig).gasLimit; + } else if (destChainConfig.chainFamilySelector == Internal.CHAIN_FAMILY_SELECTOR_SOL) { + // If extra args are empty, generate default values. + return _parseSolExtraArgsFromBytes(extraArgs, destChainConfig).computeUnits; + } + } + + function _parseSolExtraArgsFromBytes( + bytes calldata extraArgs, + DestChainConfig memory destChainConfig + ) internal pure returns (Client.SolExtraArgsV1 memory) { + + Client.SolExtraArgsV1 memory SolExtraArgs = _parseUnvalidatedSolExtraArgsFromBytes(extraArgs, destChainConfig.defaultTxGasLimit); + + // Check that compute units is within the allowed range + if (SolExtraArgs.computeUnits > uint256(destChainConfig.maxPerMsgGasLimit)) revert MessageGasLimitTooHigh(); + + // The Program name being invoked cannotb + if (SolExtraArgs.accounts[0].isWritable) revert SolAddressCannotBeWritable(SolExtraArgs.accounts[0].pubKey); + + // Check that every other account provided is a valid Sol Account + for (uint256 i = 0; i < SolExtraArgs.accounts.length; ++i) { + Internal._validateSolAddress(SolExtraArgs.accounts[i].pubKey); + } + + return SolExtraArgs; + } + + function _parseUnvalidatedSolExtraArgsFromBytes( + bytes calldata extraArgs, + uint64 defaultTxGasLimit + ) internal pure returns (Client.SolExtraArgsV1 memory) { + if (extraArgs.length == 0) { + return Client.SolExtraArgsV1({ + computeUnits: uint32(defaultTxGasLimit), //TODO: Potentially unsafe cast + accounts: new Client.SolanaAccountMeta[](0) + }); + } + + bytes memory argsData = extraArgs[4:]; + + Client.SolExtraArgsV1 memory solExtraArgs = abi.decode(argsData, (Client.SolExtraArgsV1)); + + return solExtraArgs; } /// @dev Convert the extra args bytes into a struct with validations against the dest chain config. @@ -1039,11 +1095,8 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, DestChainConfig memory destChainConfig = destChainConfigArg.destChainConfig; // destChainSelector must be non-zero, defaultTxGasLimit must be set, and must be less than maxPerMsgGasLimit. - // Only EVM chains are supported for now, additional validation logic will be added when supporting other chain - // families if ( destChainSelector == 0 || destChainConfig.defaultTxGasLimit == 0 - || destChainConfig.chainFamilySelector != Internal.CHAIN_FAMILY_SELECTOR_EVM || destChainConfig.defaultTxGasLimit > destChainConfig.maxPerMsgGasLimit ) { revert InvalidDestChainConfig(destChainSelector); diff --git a/contracts/src/v0.8/ccip/libraries/Client.sol b/contracts/src/v0.8/ccip/libraries/Client.sol index b1e1ca4a7c5..d07f4498051 100644 --- a/contracts/src/v0.8/ccip/libraries/Client.sol +++ b/contracts/src/v0.8/ccip/libraries/Client.sol @@ -42,6 +42,9 @@ library Client { // bytes4(keccak256("CCIP EVMExtraArgsV2")); bytes4 public constant EVM_EXTRA_ARGS_V2_TAG = 0x181dcf10; + // bytes4(keccak256("CCIP SolExtraArgsV1")); + bytes4 public constant SOL_EXTRA_EXTRA_ARGS_V1_TAG = 0x3f2538fa; + /// @param gasLimit: gas limit for the callback on the destination chain. /// @param allowOutOfOrderExecution: if true, it indicates that the message can be executed in any order relative to /// other messages from the same sender. This value's default varies by chain. On some chains, a particular value is @@ -51,6 +54,16 @@ library Client { bool allowOutOfOrderExecution; } + struct SolExtraArgsV1 { + uint32 computeUnits; + SolanaAccountMeta[] accounts; + } + + struct SolanaAccountMeta { + bytes pubKey; + bool isWritable; + } + function _argsToBytes( EVMExtraArgsV2 memory extraArgs ) internal pure returns (bytes memory bts) { diff --git a/contracts/src/v0.8/ccip/libraries/Internal.sol b/contracts/src/v0.8/ccip/libraries/Internal.sol index 25d923ee1ed..a6f3a24d984 100644 --- a/contracts/src/v0.8/ccip/libraries/Internal.sol +++ b/contracts/src/v0.8/ccip/libraries/Internal.sol @@ -10,6 +10,7 @@ import {MerkleMultiProof} from "../libraries/MerkleMultiProof.sol"; /// expect to have migrated to a new version by then. library Internal { error InvalidEVMAddress(bytes encodedAddress); + error InvalidSolAddress(bytes SolAddress); /// @dev We limit return data to a selector plus 4 words. This is to avoid malicious contracts from returning /// large amounts of data and causing repeated out-of-gas scenarios. @@ -173,6 +174,13 @@ library Internal { return address(uint160(encodedAddressUint)); } + // TODO: Comments for why this single check is done here so that it is future thinking + function _validateSolAddress( + bytes memory solAddress + ) internal pure { + if (solAddress.length != 32) revert InvalidSolAddress(solAddress); + } + /// @notice Enum listing the possible message execution states within the offRamp contract. /// UNTOUCHED never executed. /// IN_PROGRESS currently being executed, used a replay protection. @@ -262,6 +270,9 @@ library Internal { // bytes4(keccak256("CCIP ChainFamilySelector EVM")); bytes4 public constant CHAIN_FAMILY_SELECTOR_EVM = 0x2812d52c; + // bytes4(keccak256("CCIP ChainFamilySelector SOL")); + bytes4 public constant CHAIN_FAMILY_SELECTOR_SOL = 0x2d4dfc1c; + /// @dev Holds a merkle root and interval for a source chain so that an array of these can be passed in the CommitReport. /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. /// @dev inefficient struct packing intentionally chosen to maintain order of specificity. Not a storage struct so impact is minimal. diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getValidatedFee.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getValidatedFee.t.sol index 54832a30783..755dc6bf595 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getValidatedFee.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getValidatedFee.t.sol @@ -201,6 +201,24 @@ contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup { s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); } + // TODO: Finish + // function test_SolChainFamilySelector() public { + // // Update config to enforce allowOutOfOrderExecution = true. + // vm.stopPrank(); + // vm.startPrank(OWNER); + + // FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); + // destChainConfigArgs[0].destChainConfig.chainFamilySelector = Internal.CHAIN_FAMILY_SELECTOR_SOL; + + // s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); + // vm.stopPrank(); + + // Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + // // Empty extraArgs to should revert since it enforceOutOfOrder is true. + + // s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); + // } + // Reverts function test_RevertWhen_DestinationChainNotEnabled() public {