Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const { deployOnBase } = require("../../utils/deploy-l2");
const addresses = require("../../utils/addresses");

// Executed by base.governor 5/8 -> Base Timelock (these setters are onlyGovernor).
// Re-points the Base CrossChainRemoteStrategy operator and the OETHBaseVault
// operatorAddr to the new Talos signer, and unpauses OETHb rebases so Talos can
// rebase the vault directly (operator-gated) — replacing the PermissionedRebaseModule.
module.exports = deployOnBase(
{
deployName: "051_migrate_base_operators_to_talos",
},
async () => {
const cCrossChainRemoteStrategy = await ethers.getContractAt(
"CrossChainRemoteStrategy",
addresses.base.CrossChainRemoteStrategy
);

const cOETHbVaultProxy = await ethers.getContract("OETHBaseVaultProxy");
const cOETHbVault = await ethers.getContractAt(
"IVault",
cOETHbVaultProxy.address
);

return {
name: "Migrate the Base CrossChainRemoteStrategy operator and OETHBaseVault operatorAddr to the new Talos signer, and unpause OETHb rebases.",
actions: [
{
contract: cCrossChainRemoteStrategy,
signature: "setOperator(address)",
args: [addresses.talosRelayer],
},
{
contract: cOETHbVault,
signature: "setOperatorAddr(address)",
args: [addresses.talosRelayer],
},
{
contract: cOETHbVault,
signature: "unpauseRebase()",
args: [],
},
],
};
}
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
const addresses = require("../../utils/addresses");
const { deploymentWithGnosisSafe } = require("../../utils/deploy");

// The Base MerklPoolBoosterBribesModule is admined by the multichainStrategist
// 2/8 Safe (its DEFAULT_ADMIN_ROLE holder), so granting OPERATOR_ROLE to the new
// Talos signer is a plain Safe transaction
module.exports = deploymentWithGnosisSafe(
{
deployName: "052_migrate_base_merkl_module_to_talos",
safe: addresses.multichainStrategist,
network: "base",
forceDeploy: false,
},
async () => {
const cMerklModule = await ethers.getContractAt(
"MerklPoolBoosterBribesModule",
addresses.base.MerklPoolBoosterBribesModule
);

const OPERATOR_ROLE = ethers.utils.keccak256(
ethers.utils.toUtf8Bytes("OPERATOR_ROLE")
);

return {
name: "Grant the OPERATOR_ROLE of the Base MerklPoolBoosterBribesModule to the new Talos signer, and revoke it from the old relayer.",
actions: [
{
contract: cMerklModule,
signature: "grantRole(bytes32,address)",
args: [OPERATOR_ROLE, addresses.talosRelayer],
},
// grantRole is additive — the old relayer keeps OPERATOR_ROLE, so revoke it.
{
contract: cMerklModule,
signature: "revokeRole(bytes32,address)",
args: [OPERATOR_ROLE, addresses.base.OZRelayerAddress],
},
],
};
}
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
const addresses = require("../../utils/addresses");
const { deploymentWithGnosisSafe } = require("../../utils/deploy");

// ClaimBribesSafeModule1 is admined by the ClaimBribes 2/8 Safe (its
// DEFAULT_ADMIN_ROLE holder and immutable safeContract()), so granting
// OPERATOR_ROLE to the new Talos signer is a plain Safe transaction.
module.exports = deploymentWithGnosisSafe(
{
deployName: "053_grant_base_claim_bribes_module1_talos",
network: "base",
forceDeploy: false,
},
async () => {
const cModule = await ethers.getContract("ClaimBribesSafeModule1");
const safe = await cModule.safeContract();

const OPERATOR_ROLE = ethers.utils.keccak256(
ethers.utils.toUtf8Bytes("OPERATOR_ROLE")
);

return {
safe,
name: "Grant the OPERATOR_ROLE of the Base ClaimBribesSafeModule1 to the new Talos signer, and revoke it from the old relayer.",
actions: [
{
contract: cModule,
signature: "grantRole(bytes32,address)",
args: [OPERATOR_ROLE, addresses.talosRelayer],
},
// grantRole is additive — the old relayer keeps OPERATOR_ROLE, so revoke it.
{
contract: cModule,
signature: "revokeRole(bytes32,address)",
args: [OPERATOR_ROLE, addresses.base.OZRelayerAddress],
},
],
};
}
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
const addresses = require("../../utils/addresses");
const { deploymentWithGnosisSafe } = require("../../utils/deploy");

// ClaimBribesSafeModule3 is admined by the base.strategist 1/2 Safe (its
// DEFAULT_ADMIN_ROLE holder and immutable safeContract()), so granting
// OPERATOR_ROLE to the new Talos signer is a plain Safe transaction.
module.exports = deploymentWithGnosisSafe(
{
deployName: "054_grant_base_claim_bribes_module3_talos",
network: "base",
forceDeploy: false,
},
async () => {
const cModule = await ethers.getContract("ClaimBribesSafeModule3");
const safe = await cModule.safeContract();

const OPERATOR_ROLE = ethers.utils.keccak256(
ethers.utils.toUtf8Bytes("OPERATOR_ROLE")
);

return {
safe,
name: "Grant the OPERATOR_ROLE of the Base ClaimBribesSafeModule3 to the new Talos signer, and revoke it from the old relayer.",
actions: [
{
contract: cModule,
signature: "grantRole(bytes32,address)",
args: [OPERATOR_ROLE, addresses.talosRelayer],
},
// grantRole is additive — the old relayer keeps OPERATOR_ROLE, so revoke it.
{
contract: cModule,
signature: "revokeRole(bytes32,address)",
args: [OPERATOR_ROLE, addresses.base.OZRelayerAddress],
},
],
};
}
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const { deployOnHyperEVM } = require("../../utils/deploy-l2");
const addresses = require("../../utils/addresses");

// Re-point the HyperEVM CrossChainRemoteStrategy operator to the new Talos KMS
// signer (from the old relayer 0xC79A…0517). setOperator is onlyGovernor and the
// strategy's governor is the HyperEVM Timelock, so this is executed via that
// timelock (scheduled/executed by the hyperevm 5/8 admin). deployOnHyperEVM
// writes the schedule + execute Safe Transaction Builder JSON for the 5/8 admin.
module.exports = deployOnHyperEVM(
{
deployName: "003_migrate_crosschain_strategy_to_talos",
},
async () => {
const cCrossChainRemoteStrategy = await ethers.getContractAt(
"CrossChainRemoteStrategy",
addresses.hyperevm.CrossChainRemoteStrategy
);

return {
name: "Migrate the HyperEVM CrossChainRemoteStrategy operator to the new Talos signer.",
actions: [
{
contract: cCrossChainRemoteStrategy,
signature: "setOperator(address)",
args: [addresses.talosRelayer],
},
],
};
}
);
73 changes: 73 additions & 0 deletions contracts/deploy/mainnet/196_migrate_operators_to_talos_kms.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
const addresses = require("../../utils/addresses");
const { deploymentWithGovernanceProposal } = require("../../utils/deploy");

// the governor to execute this proposal is OGN governance
module.exports = deploymentWithGovernanceProposal(
{
deployName: "196_migrate_operators_to_talos",
forceDeploy: false,
reduceQueueTime: true,
deployerIsProposer: false,
proposalId: "", // fill in after the proposal is submitted on-chain
},
async () => {
// OUSD Vault (proxy "VaultProxy") + OETH Vault — IVault exposes both setters
const cVaultProxy = await ethers.getContract("VaultProxy");
const cOUSDVault = await ethers.getContractAt(
"IVault",
cVaultProxy.address
);

const cOETHVaultProxy = await ethers.getContract("OETHVaultProxy");
const cOETHVault = await ethers.getContractAt(
"IVault",
cOETHVaultProxy.address
);

// Cross-chain strategies (same contract code, two Create2 proxies)
const cCrossChainMasterStrategy = await ethers.getContractAt(
"CrossChainMasterStrategy",
addresses.mainnet.CrossChainMasterStrategy
);
const cCrossChainHyperEVMMasterStrategy = await ethers.getContractAt(
"CrossChainMasterStrategy",
addresses.mainnet.CrossChainHyperEVMMasterStrategy
);

return {
name: "Migrate scheduled-action operator of the OUSD/OETH vaults and the Crosschain (Base + HyperEVM) strategies to the new signer, and unpause OUSD/OETH rebases.",
actions: [
{
contract: cOUSDVault,
signature: "setOperatorAddr(address)",
args: [addresses.talosRelayer],
},
{
contract: cOETHVault,
signature: "setOperatorAddr(address)",
args: [addresses.talosRelayer],
},
{
contract: cCrossChainMasterStrategy,
signature: "setOperator(address)",
args: [addresses.talosRelayer],
},
{
contract: cCrossChainHyperEVMMasterStrategy,
signature: "setOperator(address)",
args: [addresses.talosRelayer],
},
{
contract: cOUSDVault,
signature: "unpauseRebase()",
args: [],
},
{
contract: cOETHVault,
signature: "unpauseRebase()",
args: [],
},
],
};
}
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
const addresses = require("../../utils/addresses");
const { deploymentWithGnosisSafe } = require("../../utils/deploy");

// the governor to execute this proposal is Gnosis 5/8 Multisig
module.exports = deploymentWithGnosisSafe(
{
deployName: "197_migrate_xogn_module6_to_talos",
safe: addresses.mainnet.Guardian,
forceDeploy: false,
},
async () => {
const cCollectXOGNRewardsModule6 = await ethers.getContract(
"CollectXOGNRewardsModule6"
);

const OPERATOR_ROLE = ethers.utils.keccak256(
ethers.utils.toUtf8Bytes("OPERATOR_ROLE")
);

return {
name: "Grant the OPERATOR_ROLE of CollectXOGNRewardsModule6 to the new Talos signer, and revoke it from the old relayer.",
actions: [
{
contract: cCollectXOGNRewardsModule6,
signature: "grantRole(bytes32,address)",
args: [OPERATOR_ROLE, addresses.talosRelayer],
},
// grantRole is additive — the old relayer keeps OPERATOR_ROLE, so revoke it.
{
contract: cCollectXOGNRewardsModule6,
signature: "revokeRole(bytes32,address)",
args: [OPERATOR_ROLE, addresses.mainnet.validatorRegistrator],
},
],
};
}
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const addresses = require("../../utils/addresses");
const { deploymentWithGnosisSafe } = require("../../utils/deploy");

// the governor to execute this proposal is 2/8 Cross chain strategist
module.exports = deploymentWithGnosisSafe(
{
deployName: "198_migrate_strategist_modules_to_talos",
safe: addresses.multichainStrategist,
forceDeploy: false,
},
async () => {
const moduleNames = [
"ClaimStrategyRewardsSafeModule",
"AutoWithdrawalModule",
"MerklPoolBoosterBribesModule",
"CurvePoolBoosterBribesModule",
];
const modules = [];
for (const name of moduleNames) {
modules.push(await ethers.getContract(name));
}

const OPERATOR_ROLE = ethers.utils.keccak256(
ethers.utils.toUtf8Bytes("OPERATOR_ROLE")
);

return {
name: "Grant the OPERATOR_ROLE of all strategist safe modules to the new Talos signer, and revoke it from the old relayer.",
// grantRole is additive — the old relayer keeps OPERATOR_ROLE, so for each
// module grant the new signer AND revoke the old relayer.
actions: modules.flatMap((cModule) => [
{
contract: cModule,
signature: "grantRole(bytes32,address)",
args: [OPERATOR_ROLE, addresses.talosRelayer],
},
{
contract: cModule,
signature: "revokeRole(bytes32,address)",
args: [OPERATOR_ROLE, addresses.mainnet.validatorRegistrator],
},
]),
};
}
);
Loading
Loading