Skip to content

Commit

Permalink
combined the prover proposal scripts (#1585)
Browse files Browse the repository at this point in the history
* combined the prover proposal scripts

* update the instructions on the read me for creating prover proposals

* switched comparison operator from == to === so that the comparison occurs without type conversions - thus it checks equality for both type and value

* modify language in console statement

* better error handling

* declare local obj for safe transaction from sdk so that it can be forward compatible, update env variable name to clearly indicate that the proxy contract address is needed

* rearrange error handling

* readme update to reflect the the new env variable name required for the LC proxy address

* adjust invalid command check

* allow the return type to be the command const
  • Loading branch information
alysiahuggins authored Jul 2, 2024
1 parent e0d75d6 commit ecec878
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 144 deletions.
2 changes: 1 addition & 1 deletion .env
Original file line number Diff line number Diff line change
Expand Up @@ -135,5 +135,5 @@ SAFE_MULTISIG_ADDRESS=
SAFE_ORCHESTRATOR_PRIVATE_KEY=

# Light Client
LIGHT_CLIENT_CONTRACT_ADDRESS=
LIGHT_CLIENT_PROXY_CONTRACT_ADDRESS=
APPROVED_PROVER_ADDRESS=
8 changes: 4 additions & 4 deletions contracts/script/multisigTransactionProposals/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ in the `.env` file:
- `SAFE_ORCHESTRATOR_PRIVATE_KEY`
- `SAFE_MULTISIG_ADDRESS`
- `APPROVED_PROVER_ADDRESS`
- `LIGHT_CLIENT_CONTRACT_ADDRESS`
- `LIGHT_CLIENT_PROXY_CONTRACT_ADDRESS`

Assuming you're in the root folder, run the following command:

```bash
ts-node contracts/script/multisigTransactionProposals/safeSDK/setProverProposal.ts
ts-node contracts/script/multisigTransactionProposals/safeSDK/modifyProverModeProposal.ts setProver
```

Open the the URL shown in the console to sign the transaction in the Safe UI.
Expand All @@ -39,12 +39,12 @@ in the `.env` file:
- `SEPOLIA_RPC_URL`
- `SAFE_ORCHESTRATOR_PRIVATE_KEY`
- `SAFE_MULTISIG_ADDRESS`
- `LIGHT_CLIENT_CONTRACT_ADDRESS`
- `LIGHT_CLIENT_PROXY_CONTRACT_ADDRESS`

Assuming you're in the root folder, run the following command:

```bash
ts-node contracts/script/multisigTransactionProposals/safeSDK/disableProverProposal.ts
ts-node contracts/script/multisigTransactionProposals/safeSDK/modifyProverModeProposal.ts disableProver
```

Once successful, all signers will see a transaction request on the SAFE UI
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,19 @@ import { ethers } from "ethers";
import { EthersAdapter } from "@safe-global/protocol-kit";
import SafeApiKit from "@safe-global/api-kit";
import Safe from "@safe-global/protocol-kit";
import { getEnvVar, createSafeTransactionData, isValidEthereumAddress } from "./utils";
import { getEnvVar, createSafeTransactionData, validateEthereumAddress } from "./utils";
const SET_PROVER_CMD = "setProver" as const;
const DISABLE_PROVER_CMD = "disableProver" as const;

// declaring the type returned by the createTransaction method in the safe package locally (since the return type isn't exposed) so that if it's updated, it's reflected here too
type LocalSafeTransaction = Awaited<ReturnType<Safe["createTransaction"]>>;

async function main() {
dotenv.config();

try {
const command = processCommandLineArguments();

/**TODO
* change from SEPOLIA_RPC_URL to production URL when deploying to production
*/
Expand All @@ -26,19 +33,26 @@ async function main() {
const chainId = await ethAdapter.getChainId();
const safeService = new SafeApiKit({ chainId });
const safeAddress = getEnvVar("SAFE_MULTISIG_ADDRESS");
isValidEthereumAddress(safeAddress);
validateEthereumAddress(safeAddress);
const safeSdk = await Safe.create({ ethAdapter, safeAddress });

const permissionedProverAddress = getEnvVar("APPROVED_PROVER_ADDRESS");
isValidEthereumAddress(permissionedProverAddress);

await proposeSetProverTransaction(
safeSdk,
safeService,
await orchestratorSigner.getAddress(),
safeAddress,
permissionedProverAddress,
);
const orchestratorSignerAddress = await orchestratorSigner.getAddress();

if (command === SET_PROVER_CMD) {
console.log(`${command}`);
const permissionedProverAddress = getEnvVar("APPROVED_PROVER_ADDRESS");
validateEthereumAddress(permissionedProverAddress);

await proposeSetProverTransaction(
safeSdk,
safeService,
orchestratorSignerAddress,
safeAddress,
permissionedProverAddress,
);
} else if (command === DISABLE_PROVER_CMD) {
console.log(`${command}`);
await proposeDisableProverTransaction(safeSdk, safeService, orchestratorSignerAddress, safeAddress);
}

console.log(
`The other owners of the Safe Multisig wallet need to sign the transaction via the Safe UI https://app.safe.global/transactions/queue?safe=sep:${safeAddress}`,
Expand All @@ -48,6 +62,21 @@ async function main() {
}
}

function processCommandLineArguments() {
const args = process.argv.slice(2); // Remove the first two args (node command and script name)
if (args.length === 0) {
console.log("No commands provided.");
throw new Error(`No commands provided, either ${SET_PROVER_CMD} or ${DISABLE_PROVER_CMD}`);
}

const command = args[0];
if (command !== SET_PROVER_CMD && command !== DISABLE_PROVER_CMD) {
throw new Error(`Unrecognized command ${command} provided, either ${SET_PROVER_CMD} or ${DISABLE_PROVER_CMD}`);
}

return command;
}

/**
* Function to propose the transaction data for setting the permissioned prover
* @param {string} safeSDK - An instance of the Safe SDK
Expand All @@ -66,8 +95,8 @@ export async function proposeSetProverTransaction(
// Prepare the transaction data to set the permissioned prover
let data = createPermissionedProverTxData(proverAddress);

const contractAddress = getEnvVar("LIGHT_CLIENT_CONTRACT_ADDRESS");
isValidEthereumAddress(contractAddress);
const contractAddress = getEnvVar("LIGHT_CLIENT_PROXY_CONTRACT_ADDRESS");
validateEthereumAddress(contractAddress);

// Create the Safe Transaction Object
const safeTransaction = await createSafeTransaction(safeSDK, contractAddress, data, "0");
Expand Down Expand Up @@ -102,6 +131,57 @@ function createPermissionedProverTxData(proverAddress: string): string {
return data; // Return the encoded transaction data
}

/**
* Function to propose the transaction data for disabling permissioned prover mode
* @param {Safe} safeSDK - An instance of the Safe SDK
* @param {SafeApiKit} safeService - An instance of the Safe Service
* @param {string} signerAddress - The address of the address signing the transaction
* @param {string} safeAddress - The address of the Safe multisig wallet
*/
export async function proposeDisableProverTransaction(
safeSDK: Safe,
safeService: SafeApiKit,
signerAddress: string,
safeAddress: string,
) {
// Prepare the transaction data to disable permissioned prover mode
let data = createDisablePermissionedProverTxData();

const contractAddress = getEnvVar("LIGHT_CLIENT_PROXY_CONTRACT_ADDRESS");
validateEthereumAddress(contractAddress);

// Create the Safe Transaction Object
const safeTransaction = await createSafeTransaction(safeSDK, contractAddress, data, "0");

// Get the transaction hash and sign the transaction
const safeTxHash = await safeSDK.getTransactionHash(safeTransaction);

// Sign the transaction with orchestrator signer that was specified when we created the safeSDK
const senderSignature = await safeSDK.signHash(safeTxHash);

// Propose the transaction which can be signed by other owners via the Safe UI
await safeService.proposeTransaction({
safeAddress: safeAddress,
safeTransactionData: safeTransaction.data,
safeTxHash: safeTxHash,
senderAddress: signerAddress,
senderSignature: senderSignature.data,
});
}

/**
* Function to create the transaction data for disabling permissioned prover mode
* @returns {string} - Encoded transaction data
*/
function createDisablePermissionedProverTxData(): string {
// Define the ABI of the function to be called
const abi = ["function disablePermissionedProverMode()"];

// Encode the function call with the provided prover address
const data = new ethers.Interface(abi).encodeFunctionData("disablePermissionedProverMode", []);
return data; // Return the encoded transaction data
}

/**
* Creates a Safe transaction object
*
Expand All @@ -116,7 +196,7 @@ async function createSafeTransaction(
contractAddress: string,
data: string,
value: string,
): Promise<any> {
): Promise<LocalSafeTransaction> {
// Prepare the safe transaction data with the contract address, data, and value
let safeTransactionData = createSafeTransactionData(contractAddress, data, value);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ import { ethers } from "ethers"; // Import ethers from the ethers library
/**
* Function to check if a given string is a valid Ethereum address
* @param {string} address - The Ethereum address to validate
* @returns {boolean} - Returns true if the address is valid, throws an error otherwise
* @throws {Error} - Throws an error if the address is invalid and doesn't follow Ethereum address standards
*/
export function isValidEthereumAddress(address: string) {
export function validateEthereumAddress(address: string) {
if (!ethers.isAddress(address)) {
throw new Error("Invalid Ethereum address format"); // Throw an error if the address is invalid
throw new Error(`Invalid Ethereum address format: ${address}`); // Throw an error if the address is invalid
}
return true; // Return true if the address is valid
}

/**
Expand Down Expand Up @@ -42,7 +41,7 @@ export function createSafeTransactionData(to: string, data: string, value: strin
if (data == "" && value == "") {
throw new Error("Either the contract data or value to be sent must be specified"); // Throw an error if both data and value are empty
}
isValidEthereumAddress(to); // Validate the destination address
validateEthereumAddress(to); // Validate the destination address
// Create the safe transaction data object
const safeTransactionData = {
to: to,
Expand Down

0 comments on commit ecec878

Please sign in to comment.