Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: admin scripts #350

Merged
merged 5 commits into from
Feb 9, 2024
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
100 changes: 100 additions & 0 deletions scripts/admin/tripCommon.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { BigNumberish, Contract, Wallet, utils } from "ethers";
import {
IntegrationTypes,
ChainSlug,
DeploymentMode,
isTestnet,
isMainnet,
} from "../../src";
import { mode, overrides } from "../deploy/config";
import { arrayify, defaultAbiCoder, keccak256 } from "ethers/lib/utils";
import { UN_TRIP_PATH_SIG_IDENTIFIER, checkRole, getSiblings } from "../common";
import {
getAllAddresses,
DeploymentAddresses,
ROLES,
} from "@socket.tech/dl-core";
import dotenv from "dotenv";
import { getSwitchboardInstance } from "../common";

dotenv.config();
export const deploymentMode = process.env.DEPLOYMENT_MODE as DeploymentMode;

export type SummaryObj = {
chain: ChainSlug;
siblingChain?: ChainSlug;
nonce: number;
currentTripStatus: boolean;
newTripStatus: boolean;
signature: string;
hasRole: boolean;
gasLimit?: BigNumberish;
gasPrice?: BigNumberish;
type?: number;
};

/**
* Usable flags
* --sendtx Send trip tx
* Default is false, only check trip status.
* Eg. npx --sendtx ts-node scripts/admin/rescueFunds.ts

* --chains Run only for specified chains.
* Default is all chains.
* Eg. npx --chains=10,2999 ts-node scripts/admin/tripGlobal.ts
*
* --sibling_chains Run only for specified sibling chains. (used for unTripPath only)
* Default is all sibling chains.
* Eg. npx --sibling_chains=10,2999 ts-node scripts/admin/tripGlobal.ts
*
* --testnets Run for testnets.
* Default is false.
*
* --integration Run for sepcified integration type. Can be fast or optimistic.
* Default is fast.
*/

export const addresses: DeploymentAddresses = getAllAddresses(mode);
export const testnets = process.env.npm_config_testnets == "true";
export let activeChainSlugs: string[];
if (testnets)
activeChainSlugs = Object.keys(addresses).filter((c) =>
isTestnet(parseInt(c))
);
else
activeChainSlugs = Object.keys(addresses).filter((c) =>
isMainnet(parseInt(c))
);
export const sendTx = process.env.npm_config_sendtx == "true";
export const trip = process.env.npm_config_trip == "true";
export const untrip = process.env.npm_config_untrip == "true";
export const integrationType = process.env.npm_config_integration
? process.env.npm_config_integration.toUpperCase()
: IntegrationTypes.fast;
export let filterChains = process.env.npm_config_chains
? process.env.npm_config_chains.split(",").map((c) => Number(c))
: activeChainSlugs.map((c) => Number(c));

export let siblingFilterChains = process.env.npm_config_sibling_chains
? process.env.npm_config_sibling_chains.split(",").map((c) => Number(c))
: undefined;

export const printSummary = (summary: SummaryObj[]) => {
console.log("\n======== UPDATE SUMMARY ==========\n");
for (let summaryObj of summary) {
let { chain, ...rest } = summaryObj;
console.log(formatMsg(String(chain), rest));
}
};

export const formatMsg = (title: string, data: any) => {
let message = `====== ${title} ======\n`;

// Iterate through the object's key-value pairs
for (const key in data) {
if (data.hasOwnProperty(key)) {
message += `${key}: ${data[key]}\n`;
}
}
return message;
};
228 changes: 228 additions & 0 deletions scripts/admin/tripGlobal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
import {
IntegrationTypes,
ChainSlug,
DeploymentMode,
isTestnet,
isMainnet,
} from "../../src";
import { mode, overrides } from "../deploy/config";
import { arrayify, defaultAbiCoder, keccak256 } from "ethers/lib/utils";
import {
UN_TRIP_GLOBAL_SIG_IDENTIFIER,
UN_TRIP_NATIVE_SIG_IDENTIFIER,
checkRole,
getSiblings,
getSwitchboardInstance,
TRIP_GLOBAL_SIG_IDENTIFIER,
TRIP_NATIVE_SIG_IDENTIFIER,
} from "../common";
import { ROLES } from "@socket.tech/dl-core";
import dotenv from "dotenv";
import {
sendTx,
integrationType,
filterChains,
SummaryObj,
printSummary,
trip,
untrip,
deploymentMode,
formatMsg,
} from "./tripCommon";
import { BigNumberish, Contract } from "ethers";

/**
* Usable flags
*
* --trip trip Global
* Eg. npx --untrip ts-node scripts/admin/rescueFunds.ts
*
* --untrip unTrip Global
* Eg. npx --untrip ts-node scripts/admin/rescueFunds.ts
*
* --sendtx Send trip tx
* Default is false, only check trip status.
* Eg. npx --sendtx ts-node scripts/admin/rescueFunds.ts

* --chains Run only for specified chains.
* Default is all chains.
* Eg. npx --chains=10,2999 ts-node scripts/admin/tripGlobal.ts
*
* --testnets Run for testnets.
* Default is false.
*
* --integration Run for sepcified integration type. Can be fast or optimistic.
* Default is fast.
*/

const main = async () => {
if (trip && untrip) {
console.log("both trip and untrip flags cant be passed. pass one of them.");
return;
}
if (!trip && !untrip) {
console.log("pass one of trip or untrip flag.");
return;
}

if (
integrationType &&
!Object.values(IntegrationTypes).includes(
integrationType as IntegrationTypes
)
) {
throw new Error(
"Invalid integration type. Can be FAST, NATIVE_BRIDGE or OPTIMISTIC"
);
}
console.log(
formatMsg("Config", { trip, untrip, integrationType, filterChains, sendTx })
);

let summary: SummaryObj[] = [];

for (const chain of filterChains) {
let siblingChains = getSiblings(deploymentMode, Number(chain) as ChainSlug);

if (!siblingChains.length) {
console.log("No siblings found for ", chain, " continuing...");
continue;
}
console.log("\nChecking chain: ", chain);
let siblingChain = siblingChains[0];

const switchboard = getSwitchboardInstance(
chain,
siblingChain,
integrationType as IntegrationTypes,
mode
);
if (switchboard === undefined) {
console.log("Switchboard address not found for ", chain, "continuing...");
continue;
}

let tripStatus: boolean;
try {
tripStatus = await switchboard.isGlobalTipped();
console.log("trip status: ", tripStatus);
} catch (error) {
console.log("RPC Error while fetching trip status: ", error);
continue;
}

if (trip && tripStatus) continue;
if (untrip && !tripStatus) continue;

let userAddress = await switchboard.signer.getAddress();
let role: string;
if (trip) role = ROLES.TRIP_ROLE;
if (untrip) role = ROLES.UN_TRIP_ROLE;

let hasRole = await checkRole(role, switchboard, userAddress);
if (!hasRole) {
console.log(
`${userAddress} doesn't have ${role} for contract ${switchboard.address}`
);
continue;
}
const nonce = await switchboard.nextNonce(userAddress);
let signature = await getSignature(chain, nonce, switchboard);

summary.push({
chain,
hasRole,
currentTripStatus: tripStatus,
newTripStatus: !tripStatus,
signature,
nonce,
...overrides(chain),
});

if (sendTx) {
sendTxn(chain, nonce, signature, switchboard, trip, untrip);
}
}
printSummary(summary);
};

const sendTxn = async (
chain: ChainSlug,
nonce: number,
signature: string,
switchboard: Contract,
trip: boolean,
untrip: boolean
) => {
let tx;
if (trip)
tx = await switchboard.tripGlobal(nonce, signature, {
...overrides(chain),
});
if (untrip)
tx = await switchboard.unTrip(nonce, signature, {
...overrides(chain),
});
console.log(tx.hash);

await tx.wait();
console.log("done");
};

const getSignature = async (
chain: ChainSlug,
nonce: number,
switchboard: Contract
) => {
if (trip) {
let sigIdentifier =
integrationType == IntegrationTypes.native
? TRIP_NATIVE_SIG_IDENTIFIER
: TRIP_GLOBAL_SIG_IDENTIFIER;
const digest = keccak256(
defaultAbiCoder.encode(
["bytes32", "address", "uint32", "uint256", "bool"],
[sigIdentifier, switchboard.address, chain, nonce, true]
)
);

return await switchboard.signer.signMessage(arrayify(digest));
}

if (untrip) {
let sigIdentifier =
integrationType == IntegrationTypes.native
? UN_TRIP_NATIVE_SIG_IDENTIFIER
: UN_TRIP_GLOBAL_SIG_IDENTIFIER;

const digest = keccak256(
defaultAbiCoder.encode(
["bytes32", "address", "uint32", "uint256", "bool"],
[sigIdentifier, switchboard.address, chain, nonce, false]
)
);

return await switchboard.signer.signMessage(arrayify(digest));
}
};

main()
.then(() => process.exit(0))
.catch((error: Error) => {
console.error(error);
process.exit(1);
});

// TRIP Commands
// npx --trip ts-node scripts/admin/tripGlobal.ts - check trip status for all mainnet chains
// npx --trip --chains=421614 ts-node scripts/admin/tripGlobal.ts
// npx --trip --sendtx --chains=421614 ts-node scripts/admin/tripGlobal.ts
// npx --trip --sendtx --chains=421614 --integration=fast ts-node scripts/admin/tripGlobal.ts
// npx --trip --sendtx --chains=421614 --testnets --integration=fast ts-node scripts/admin/tripGlobal.ts

// UNTRIP COMMANDS
// npx --untrip ts-node scripts/admin/tripGlobal.ts - check trip status for all mainnet chains
// npx --untrip --chains=421614 ts-node scripts/admin/tripGlobal.ts
// npx --untrip --sendtx --chains=421614 ts-node scripts/admin/tripGlobal.ts
// npx --untrip --sendtx --chains=421614 --integration=fast ts-node scripts/admin/tripGlobal.ts
// npx --untrip --sendtx --chains=421614 --testnets --integration=fast ts-node scripts/admin/tripGlobal.ts
Loading
Loading