Skip to content

Commit

Permalink
fix: reject-superproposal now works
Browse files Browse the repository at this point in the history
  • Loading branch information
Will Kim committed Jun 17, 2022
1 parent affa94b commit 468852d
Show file tree
Hide file tree
Showing 11 changed files with 278 additions and 231 deletions.
2 changes: 1 addition & 1 deletion docs/assets/search.js

Large diffs are not rendered by default.

84 changes: 62 additions & 22 deletions docs/classes/Pod.html

Large diffs are not rendered by default.

36 changes: 35 additions & 1 deletion docs/classes/Proposal.html

Large diffs are not rendered by default.

14 changes: 11 additions & 3 deletions docs/modules.html

Large diffs are not rendered by default.

33 changes: 20 additions & 13 deletions scripts/reject-superproposal.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable no-console */
import { getPod } from '../src';
import { adminPodAddress, dummyAccount, subPodAddress, subPodTwoAddress } from '../env.json';
import { setup, sleep } from './utils';
import { flush, report, setup, sleep } from './utils';

async function main() {
const { walletOne, walletTwo } = setup();
Expand All @@ -10,15 +10,21 @@ async function main() {
const subPod = await getPod(subPodAddress);
const subPodTwo = await getPod(subPodTwoAddress);

if (
(await superPod.getProposals({ status: 'queued' }))[0].status !== 'executed' ||
(await subPod.getProposals({ status: 'queued' }))[0].status !== 'executed' ||
(await subPodTwo.getProposals({ status: 'queued' }))[0].status !== 'executed'
) {
throw new Error(
'Admin or sub pod had an active/queued transaction. This script expects no enqueued transactions',
);
}
// await report();
// return;

// await flush(walletOne, walletTwo);

// if (
// (await superPod.getProposals({ status: 'queued' }))[0].status !== 'executed' ||
// (await subPod.getProposals({ status: 'queued' }))[0].status !== 'executed' ||
// (await subPodTwo.getProposals({ status: 'queued' }))[0].status !== 'executed'
// ) {
// throw new Error(
// 'Admin or sub pod had an active/queued transaction. This script expects no enqueued transactions',
// );
// }
// return;

// We mint/burn the dummy account based on whether its a member or not.
const isMember = await superPod.isMember(dummyAccount);
Expand All @@ -32,16 +38,17 @@ async function main() {
}
await superPod.propose(data, subPod.safe);
} catch (err) {
console.log(err);
throw new Error('Error creating proposal on subpod');
console.log('err', err);
throw err;
}

let [superProposal] = await superPod.getProposals();
console.log('superProposal', superProposal);
// console.log('superProposal', superProposal);

console.log('Rejecting the first sub proposal');
// This would approve the proposal, and then reject it
const subProposal = await subPod.propose(superProposal, await walletOne.getAddress());
// console.log('subProposal', subProposal);
await subProposal.reject(walletOne);
await subProposal.executeReject(walletOne);

Expand Down
60 changes: 58 additions & 2 deletions scripts/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { ethers } from 'ethers';
import { init } from '../src';
import { accountOnePrivateKey, accountTwoPrivateKey } from '../env.json';
import { init, getPod } from '../src';
import {
accountOnePrivateKey,
accountTwoPrivateKey,
adminPodAddress,
subPodAddress,
subPodTwoAddress,
} from '../env.json';

export function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
Expand All @@ -17,3 +23,53 @@ export function setup() {
const walletTwo = new ethers.Wallet(accountTwoPrivateKey, provider);
return { walletOne, walletTwo };
}

/**
* Logs out the latest proposal for each of the pods.
*/
export async function report() {
const superPod = await getPod(adminPodAddress);
const [props1] = await superPod.getProposals({ status: 'queued', limit: 1 });
console.log('props1', props1);
const subPod = await getPod(subPodAddress);
const [props2] = await subPod.getProposals({ status: 'queued', limit: 1 });
console.log('props2', props2);
const subPod2 = await getPod(subPodTwoAddress);
const [props3] = await subPod2.getProposals({ status: 'queued', limit: 1 });
console.log('props3', props3);
}

/**
* Flushes out all active transactions from the 3 pods we're using.
* You will probably have to run this a few times, and it takes a while
* for Gnosis to catch up after a run.
*/
export async function flush(walletOne, walletTwo) {
const superPod = await getPod(adminPodAddress);
const props1 = await superPod.getProposals({ status: 'queued', limit: 1 });
const subPod = await getPod(subPodAddress);
const subPodTwo = await getPod(subPodTwoAddress);

[superPod, subPod, subPodTwo].forEach(async pod => {
const props = await pod.getProposals({ status: 'queued' });
if (props[0].status === 'active') {
console.log('we in here');
try {
await props[0].approve(walletOne);
} catch (err) {
// nothing
}
try {
await props[0].approve(walletTwo);
} catch (err) {
// nothing
}
try {
await props[0].executeApprove(walletOne);
} catch (err) {
console.log('was unable to execute tx');
// nothing
}
}
});
}
4 changes: 2 additions & 2 deletions src/Pod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -661,10 +661,10 @@ export default class Pod {
data,
});
} catch (err) {
if (err.response.data.message === 'Gas estimation failed') {
if (err.response?.data.message === 'Gas estimation failed') {
throw new Error('Gas estimation failed (this is often a revert error)');
}
throw new Error(err);
throw err;
}
}

Expand Down
57 changes: 29 additions & 28 deletions src/Proposal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import {
executeSafeTransaction,
executeRejectSuperProposal,
SafeTransaction,
getSafeTransactionByHash,
} from './lib/services/transaction-service';
import { approveSuperProposal, rejectSuperProposal } from './lib/services/create-safe-transaction';
import { rejectSuperProposal } from './lib/services/create-safe-transaction';
import { checkAddress } from './lib/utils';

export type ProposalStatus = 'active' | 'executed' | 'queued';
Expand All @@ -31,7 +32,7 @@ export default class Proposal {
/**
* @property Whether or not this proposal corresponds to a superproposal
*/
isSubProposal: boolean;
isSubProposal?: boolean;

/** @property Array of addresses that approved */
approvals: string[];
Expand Down Expand Up @@ -155,6 +156,32 @@ export default class Proposal {
throw new Error('Signer was not part of this pod');
}

// When a Proposal is fetched directly after creation, e.g., from the `propose` method
// Some fields are not populated. If `this.isSubProposal` is undefined, it means that
// we fetched directly after creation, and we need to populate this value ourselves.
if (this.isSubProposal === undefined) {
// Refetch the safe transaction.
this.safeTransaction = await getSafeTransactionByHash(this.safeTransaction.safeTxHash);
if (this.safeTransaction.dataDecoded) {
this.method = this.safeTransaction.dataDecoded.method;
this.parameters = this.safeTransaction.dataDecoded.parameters;
} else {
this.method = null;
this.parameters = null;
}
this.isSubProposal = this.method === 'approveHash';
}

if (this.isSubProposal === true) {
try {
await rejectSuperProposal(this.parameters[0].value, this.pod, signer);
this.rejections.push(signerAddress);
return;
} catch (err) {
throw new Error(`Error rejecting super proposal: ${err.message}`);
}
}

if (!this.rejectTransaction) {
this.rejectTransaction = await createRejectTransaction(this.safeTransaction, signer);
} else {
Expand All @@ -168,32 +195,6 @@ export default class Proposal {
this.rejections.push(signerAddress);
};

/**
* Approves a super proposal from a sub pod. This creates a sub proposal if one does not exist.
* @param subPod - Pod to approve from
* @param signer - Signer of sub pod member
*/
approveFromSubPod = async (subPod: Pod, signer: ethers.Signer) => {
const sender = await signer.getAddress();
if (!(await this.pod.isMember(subPod.safe))) {
throw new Error(`${subPod.ensName} is not a sub pod of ${this.pod.ensName}`);
}
await approveSuperProposal({ sender, ...this.safeTransaction }, subPod, signer);
};

/**
* Rejects a super proposal from a sub pod. This creates a sub proposal if one does not exist.
* @param subPod - Pod to reject from
* @param signer - Signer of sub pod member
*/
rejectFromSubPod = async (subPod: Pod, signer: ethers.Signer) => {
const sender = await signer.getAddress();
if (!(await this.pod.isMember(subPod.safe))) {
throw new Error(`${subPod.ensName} is not a sub pod of ${this.pod.ensName}`);
}
await rejectSuperProposal({ sender, ...this.safeTransaction }, subPod, signer);
};

/**
* Executes proposal
* @param signer - Signer of pod member
Expand Down
Loading

0 comments on commit 468852d

Please sign in to comment.