Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 6 additions & 20 deletions script/configure/allowlist/UpdateAdvancedPoolHooks.s.sol
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import {Script, console} from "forge-std/Script.sol";
import {console} from "forge-std/Script.sol";
import {HelperConfig} from "../../HelperConfig.s.sol";
import {TokenPool} from "@chainlink/contracts-ccip/contracts/pools/TokenPool.sol";
import {IAdvancedPoolHooks} from "@chainlink/contracts-ccip/contracts/interfaces/IAdvancedPoolHooks.sol";
import {CctActions} from "../../../src/actions/CctActions.sol";
import {EoaExecutor} from "../../../src/base/EoaExecutor.s.sol";

/**
* @title UpdateAdvancedPoolHooks
Expand All @@ -14,7 +14,7 @@ import {IAdvancedPoolHooks} from "@chainlink/contracts-ccip/contracts/interfaces
* Usage:
* TOKEN_POOL=0x... NEW_HOOK=0x... forge script script/configure/allowlist/UpdateAdvancedPoolHooks.s.sol --rpc-url $ETHEREUM_SEPOLIA_RPC_URL --account $KEYSTORE_NAME --broadcast
*/
contract UpdateAdvancedPoolHooks is Script {
contract UpdateAdvancedPoolHooks is EoaExecutor {
HelperConfig public helperConfig;

function run() external {
Expand Down Expand Up @@ -46,22 +46,8 @@ contract UpdateAdvancedPoolHooks is Script {
console.log(string.concat("New Pool Hooks: ", vm.toString(newHookAddress)));
console.log("");

vm.startBroadcast();
TokenPool tokenPool = TokenPool(tokenPoolAddress);
try tokenPool.updateAdvancedPoolHooks(IAdvancedPoolHooks(newHookAddress)) {
vm.stopBroadcast();
console.log(unicode"✅ AdvancedPoolHooks updated successfully!");
} catch (bytes memory err) {
vm.stopBroadcast();
console.log(unicode"❌ Error: updateAdvancedPoolHooks() reverted.");
console.log(" Raw revert data:");
console.logBytes(err);
console.log(
" If the error is OnlyCallableByOwner(), ensure you are broadcasting with the pool owner's account."
);
console.log(" If the function selector is missing, the pool may be v1 (requires TokenPool v2.0+).");
revert("updateAdvancedPoolHooks() reverted - see raw error above");
}
executeCalls(CctActions.updateAdvancedPoolHooks(tokenPoolAddress, newHookAddress));
console.log(unicode"✅ AdvancedPoolHooks updated successfully!");
console.log("");
console.log("========================================");
console.log(string.concat(unicode"✅ Pool hooks updated on ", chainName, "!"));
Expand Down
57 changes: 10 additions & 47 deletions script/configure/allowlist/UpdateAllowList.s.sol
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import {Script, console} from "forge-std/Script.sol";
import {console} from "forge-std/Script.sol";
import {HelperConfig} from "../../HelperConfig.s.sol";
import {HelperUtils} from "../../utils/HelperUtils.s.sol";
import {AdvancedPoolHooks} from "@chainlink/contracts-ccip/contracts/pools/AdvancedPoolHooks.sol";

interface ITokenPoolV1 {
function applyAllowListUpdates(address[] calldata removes, address[] calldata adds) external;
}
import {CctActions} from "../../../src/actions/CctActions.sol";
import {EoaExecutor} from "../../../src/base/EoaExecutor.s.sol";

/**
* @title UpdateAllowList
Expand All @@ -19,7 +16,7 @@ interface ITokenPoolV1 {
* TOKEN_POOL=0x... POOL_HOOKS=0x... forge script script/configure/allowlist/UpdateAllowList.s.sol --rpc-url $ETHEREUM_SEPOLIA_RPC_URL --account $KEYSTORE_NAME --broadcast
* (If POOL_HOOKS is not set, will try to call on pool contract. If not found, throws error with guidance.)
*/
contract UpdateAllowList is Script {
contract UpdateAllowList is EoaExecutor {
HelperConfig public helperConfig;

function run() external {
Expand Down Expand Up @@ -56,47 +53,13 @@ contract UpdateAllowList is Script {
console.log("========================================");
console.log("");

vm.startBroadcast();
bool success = false;
string memory errorMsg = "";
if (hooksAddress != address(0)) {
// Try to call on AdvancedPoolHooks
try AdvancedPoolHooks(hooksAddress).applyAllowListUpdates(removes, adds) {
success = true;
} catch (bytes memory err) {
console.log(unicode"❌ Error: applyAllowListUpdates() reverted on AdvancedPoolHooks.");
console.log(" Raw revert data:");
console.logBytes(err);
console.log(
" If the error is OnlyCallableByOwner(), ensure you are broadcasting with the hooks owner's account."
);
errorMsg = unicode"❌ Error: applyAllowListUpdates() reverted - see raw error above.";
}
} else {
// Try to call on TokenPool (v1) via interface
try ITokenPoolV1(tokenPoolAddress).applyAllowListUpdates(removes, adds) {
success = true;
} catch (bytes memory err) {
console.log(unicode"❌ Error: applyAllowListUpdates() reverted on TokenPool.");
console.log(" Raw revert data:");
console.logBytes(err);
console.log(
" If the function selector is not found, you may be using TokenPool v2.0+ which requires AdvancedPoolHooks."
);
console.log(
" Deploy AdvancedPoolHooks using DeployAdvancedPoolHooks.s.sol, connect it via UpdateAdvancedPoolHooks.s.sol, then pass its address as POOL_HOOKS."
);
errorMsg = unicode"❌ Error: applyAllowListUpdates() reverted - see raw error above.";
}
}
vm.stopBroadcast();
// Target the AdvancedPoolHooks (v2) when POOL_HOOKS is set, otherwise the pool itself (v1). Both
// expose the identical applyAllowListUpdates(address[],address[]) selector, so one builder serves
// both. A revert (e.g. OnlyCallableByOwner, or a v2 pool without hooks) bubbles up unchanged.
address allowListTarget = hooksAddress != address(0) ? hooksAddress : tokenPoolAddress;
executeCalls(CctActions.applyAllowListUpdates(allowListTarget, removes, adds));

if (success) {
console.log(unicode"✅ AllowList updated successfully!");
} else {
console.log(errorMsg);
revert(errorMsg);
}
console.log(unicode"✅ AllowList updated successfully!");
console.log("");
console.log("========================================");
console.log(string.concat(unicode"✅ Allowlist updated on ", chainName, "!"));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import {Script, console} from "forge-std/Script.sol";
import {console} from "forge-std/Script.sol";
import {HelperConfig} from "../../HelperConfig.s.sol";
import {HelperUtils} from "../../utils/HelperUtils.s.sol";
import {AuthorizedCallers} from "@chainlink/contracts/src/v0.8/shared/access/AuthorizedCallers.sol";
import {CctActions} from "../../../src/actions/CctActions.sol";
import {EoaExecutor} from "../../../src/base/EoaExecutor.s.sol";

/**
* @title UpdateAuthorizedCallers
Expand All @@ -21,7 +22,7 @@ import {AuthorizedCallers} from "@chainlink/contracts/src/v0.8/shared/access/Aut
* ADD_ADDRESSES — CSV or JSON array of addresses to add
* REMOVE_ADDRESSES — CSV or JSON array of addresses to remove
*/
contract UpdateAuthorizedCallers is Script {
contract UpdateAuthorizedCallers is EoaExecutor {
HelperConfig public helperConfig;

function run() external {
Expand Down Expand Up @@ -71,14 +72,7 @@ contract UpdateAuthorizedCallers is Script {
}
console.log("");

vm.startBroadcast();

AuthorizedCallers(contractAddress)
.applyAuthorizedCallerUpdates(
AuthorizedCallers.AuthorizedCallerArgs({addedCallers: addCallers, removedCallers: removeCallers})
);

vm.stopBroadcast();
executeCalls(CctActions.applyAuthorizedCallerUpdates(contractAddress, addCallers, removeCallers));

console.log("");
console.log("========================================");
Expand Down
18 changes: 8 additions & 10 deletions script/configure/dynamic-config/SetDynamicConfig.s.sol
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import {Script, console} from "forge-std/Script.sol";
import {console} from "forge-std/Script.sol";
import {HelperConfig} from "../../HelperConfig.s.sol";
import {TokenPool} from "@chainlink/contracts-ccip/contracts/pools/TokenPool.sol";
import {CctActions} from "../../../src/actions/CctActions.sol";
import {EoaExecutor} from "../../../src/base/EoaExecutor.s.sol";

/// @notice Updates the dynamic configuration of a TokenPool (router, rateLimitAdmin, feeAdmin).
///
Expand All @@ -20,7 +22,7 @@ import {TokenPool} from "@chainlink/contracts-ccip/contracts/pools/TokenPool.sol
/// RATE_LIMIT_ADMIN=0xYourRateLimitAdminAddress \
/// FEE_ADMIN=0xYourFeeAdminAddress \
/// forge script script/configure/dynamic-config/SetDynamicConfig.s.sol --rpc-url $ETHEREUM_SEPOLIA_RPC_URL --account <KEYSTORE_NAME> --broadcast
contract SetDynamicConfig is Script {
contract SetDynamicConfig is EoaExecutor {
HelperConfig public helperConfig;

function run() external {
Expand Down Expand Up @@ -61,14 +63,12 @@ contract SetDynamicConfig is Script {
console.log(string.concat(" Fee Admin: ", vm.toString(currentFeeAdmin)));
console.log("");

vm.startBroadcast();

// Defaults: env var → current on-chain value → broadcaster (as last resort if unset)
(, address broadcaster,) = vm.readCallers();
address broadcasterAddr = broadcaster();
address router = vm.envOr("ROUTER", currentRouter);
address rateLimitAdmin =
vm.envOr("RATE_LIMIT_ADMIN", currentRateLimitAdmin != address(0) ? currentRateLimitAdmin : broadcaster);
address feeAdmin = vm.envOr("FEE_ADMIN", currentFeeAdmin != address(0) ? currentFeeAdmin : broadcaster);
vm.envOr("RATE_LIMIT_ADMIN", currentRateLimitAdmin != address(0) ? currentRateLimitAdmin : broadcasterAddr);
address feeAdmin = vm.envOr("FEE_ADMIN", currentFeeAdmin != address(0) ? currentFeeAdmin : broadcasterAddr);

console.log("New Configuration:");
console.log(string.concat(" Router: ", vm.toString(router)));
Expand All @@ -77,9 +77,7 @@ contract SetDynamicConfig is Script {
console.log("");
console.log(string.concat("[Step 1] Setting dynamic config on ", chainName));

tokenPool.setDynamicConfig(router, rateLimitAdmin, feeAdmin);

vm.stopBroadcast();
executeCalls(CctActions.setDynamicConfig(tokenPoolAddress, router, rateLimitAdmin, feeAdmin));

console.log(unicode"✅ Dynamic config updated successfully!");
console.log("");
Expand Down
38 changes: 9 additions & 29 deletions script/configure/fee-config/UpdateTokenTransferFeeConfig.s.sol
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import {Script, console} from "forge-std/Script.sol";
import {console} from "forge-std/Script.sol";
import {HelperConfig} from "../../HelperConfig.s.sol";
import {TokenPool} from "@chainlink/contracts-ccip/contracts/pools/TokenPool.sol";
import {IPoolV2} from "@chainlink/contracts-ccip/contracts/interfaces/IPoolV2.sol";
import {CctActions} from "../../../src/actions/CctActions.sol";
import {EoaExecutor} from "../../../src/base/EoaExecutor.s.sol";

/// @notice Applies token transfer fee configuration updates to a token pool on a given destination lane.
///
Expand Down Expand Up @@ -43,7 +45,7 @@ import {IPoolV2} from "@chainlink/contracts-ccip/contracts/interfaces/IPoolV2.so
/// DEST_CHAIN=MANTLE_SEPOLIA \
/// DISABLE=true \
/// forge script script/configure/fee-config/UpdateTokenTransferFeeConfig.s.sol --rpc-url $ETHEREUM_SEPOLIA_RPC_URL --account <KEYSTORE_NAME> --broadcast
contract UpdateTokenTransferFeeConfig is Script {
contract UpdateTokenTransferFeeConfig is EoaExecutor {
HelperConfig public helperConfig;

function run() external {
Expand Down Expand Up @@ -107,23 +109,12 @@ contract UpdateTokenTransferFeeConfig is Script {
toDisable[0] = destChainSelector;
TokenPool.TokenTransferFeeConfigArgs[] memory emptyArgs = new TokenPool.TokenTransferFeeConfigArgs[](0);

vm.startBroadcast();

// applyTokenTransferFeeConfigUpdates() was introduced in TokenPool v2.0.
// On v1 pools, fee configuration is handled by FeeQuoter and requires
// a direct request to the Chainlink team — it cannot be modified here.
try tokenPool.applyTokenTransferFeeConfigUpdates(emptyArgs, toDisable) {
console.log(unicode"✅ Fee config disabled for this lane.");
console.log(" The OnRamp will now use FeeQuoter defaults for this destination.");
} catch (bytes memory err) {
console.log(unicode"❌ Error: applyTokenTransferFeeConfigUpdates() reverted.");
console.log(" Raw revert data:");
console.logBytes(err);
console.log(" If the function selector is missing, the pool may be v1 (requires TokenPool v2.0+).");
revert("applyTokenTransferFeeConfigUpdates() reverted - see raw error above");
}

vm.stopBroadcast();
executeCalls(CctActions.applyTokenTransferFeeConfigUpdates(tokenPoolAddress, emptyArgs, toDisable));
console.log(unicode"✅ Fee config disabled for this lane.");
console.log(" The OnRamp will now use FeeQuoter defaults for this destination.");
} else {
// ── Read current on-chain config as defaults ───────────────────
IPoolV2.TokenTransferFeeConfig memory currentConfig;
Expand Down Expand Up @@ -169,22 +160,11 @@ contract UpdateTokenTransferFeeConfig is Script {
string.concat("[Step 1] Applying fee config for lane to ", helperConfig.getChainName(destChainId))
);

vm.startBroadcast();

// applyTokenTransferFeeConfigUpdates() was introduced in TokenPool v2.0.
// On v1 pools, fee configuration is handled by FeeQuoter and requires
// a direct request to the Chainlink team — it cannot be modified here.
try tokenPool.applyTokenTransferFeeConfigUpdates(args, emptyDisable) {
console.log(unicode"✅ Fee config applied successfully!");
} catch (bytes memory err) {
console.log(unicode"❌ Error: applyTokenTransferFeeConfigUpdates() reverted.");
console.log(" Raw revert data:");
console.logBytes(err);
console.log(" If the function selector is missing, the pool may be v1 (requires TokenPool v2.0+).");
revert("applyTokenTransferFeeConfigUpdates() reverted - see raw error above");
}

vm.stopBroadcast();
executeCalls(CctActions.applyTokenTransferFeeConfigUpdates(tokenPoolAddress, args, emptyDisable));
console.log(unicode"✅ Fee config applied successfully!");
}

// ── Footer ─────────────────────────────────────────────────────────
Expand Down
35 changes: 9 additions & 26 deletions script/configure/finality-config/SetFinalityConfig.s.sol
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import {Script, console} from "forge-std/Script.sol";
import {console} from "forge-std/Script.sol";
import {HelperConfig} from "../../HelperConfig.s.sol";
import {TokenPool} from "@chainlink/contracts-ccip/contracts/pools/TokenPool.sol";
import {FinalityCodec} from "@chainlink/contracts-ccip/contracts/libraries/FinalityCodec.sol";
import {RateLimiter} from "@chainlink/contracts-ccip/contracts/libraries/RateLimiter.sol";
import {RateLimiterUtils, ITokenPoolV1RateLimiter} from "../../utils/RateLimiterUtils.s.sol";
import {FinalityConfigUtils} from "../../utils/FinalityConfigUtils.s.sol";
import {CctActions} from "../../../src/actions/CctActions.sol";
import {EoaExecutor} from "../../../src/base/EoaExecutor.s.sol";

/// @notice Sets the allowed finality configuration on a TokenPool, and optionally updates rate limits
/// for the fast finality bucket on a specific remote chain lane.
Expand Down Expand Up @@ -58,7 +60,7 @@ import {FinalityConfigUtils} from "../../utils/FinalityConfigUtils.s.sol";
///
/// # Reset to default finality (disables fast finality transfers):
/// forge script script/configure/finality-config/SetFinalityConfig.s.sol --rpc-url $ETHEREUM_SEPOLIA_RPC_URL --account <KEYSTORE_NAME> --broadcast
contract SetFinalityConfig is Script {
contract SetFinalityConfig is EoaExecutor {
HelperConfig public helperConfig;

// ── Storage: avoids EVM stack pressure inside run() ────────────────────
Expand Down Expand Up @@ -145,22 +147,10 @@ contract SetFinalityConfig is Script {
}

// ── Step 1: Set finality config ────────────────────────────────────
vm.startBroadcast();

console.log(string.concat("[Step 1] Setting finality config on ", chainName));

try tokenPool.setAllowedFinalityConfig(s_newFinalityConfig) {
console.log(unicode"✅ Finality config set successfully!");
} catch (bytes memory err) {
console.log(unicode"❌ Error: setAllowedFinalityConfig() reverted.");
console.log(" Raw revert data:");
console.logBytes(err);
console.log(
" If the error is OnlyCallableByOwner(), ensure you are broadcasting with the pool owner's account."
);
console.log(" If the function selector is missing, the pool may be v1 (requires TokenPool v2.0+).");
revert("setAllowedFinalityConfig() reverted - see raw error above");
}
executeCalls(CctActions.setAllowedFinalityConfig(tokenPoolAddress, s_newFinalityConfig));
console.log(unicode"✅ Finality config set successfully!");

// ── Step 2: Apply rate limit update (if requested) ─────────────────
if (hasRateLimitUpdate) {
Expand All @@ -169,8 +159,6 @@ contract SetFinalityConfig is Script {
);
}

vm.stopBroadcast();

// ── Log updated rate limits (if DEST_CHAIN provided) ──────────────
if (destChainSet) {
console.log("");
Expand Down Expand Up @@ -262,14 +250,9 @@ contract SetFinalityConfig is Script {

RateLimiterUtils.logNewConfig(u.updateOutbound, outbound, u.updateInbound, inbound);

TokenPool.RateLimitConfigArgs[] memory args = new TokenPool.RateLimitConfigArgs[](1);
args[0] = TokenPool.RateLimitConfigArgs({
remoteChainSelector: remoteChainSelector,
fastFinality: true,
outboundRateLimiterConfig: outbound,
inboundRateLimiterConfig: inbound
});
tokenPool.setRateLimitConfig(args);
// Fast-finality bucket update (fastFinality=true) through the version-detected action dispatch.
// setAllowedFinalityConfig above already established this is a v2 pool.
executeCalls(CctActions.setRateLimits(address(tokenPool), isV2, remoteChainSelector, true, outbound, inbound));

console.log(unicode"✅ Rate limits updated successfully!");
}
Expand Down
Loading
Loading