Skip to content

Instantly share code, notes, and snippets.

@IllIllI000
Last active September 21, 2022 00:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save IllIllI000/63e170b9a07a321ceec79938ac804aa5 to your computer and use it in GitHub Desktop.
Save IllIllI000/63e170b9a07a321ceec79938ac804aa5 to your computer and use it in GitHub Desktop.
diff --git a/hardhat.config.ts b/hardhat.config.ts
index 63bb978..1ed5b79 100644
--- a/hardhat.config.ts
+++ b/hardhat.config.ts
@@ -49,6 +49,12 @@ const config: HardhatUserConfig = {
accountsBalance: "100000000000000000000000", // 100000 ETH
count: 20,
},
+ gas: 5000000,
+ mining: {
+/* mempool: {
+ order: "fifo"
+ }*/
+ }
},
mainnet: {
url: `https://eth-mainnet.alchemyapi.io/v2/${process.env.ALCHEMY_MAINNET_API_KEY}`,
diff --git a/test/votingEscrowTest.ts b/test/votingEscrowTest.ts
index 7d3163d..6fb031b 100644
--- a/test/votingEscrowTest.ts
+++ b/test/votingEscrowTest.ts
@@ -53,6 +53,49 @@ describe("VotingEscrow Tests", function () {
return (await ethers.provider.getBlock("latest")).timestamp;
}
+ async function dumpNyms(description: string, names: Map<string,SignerWithAddress>, primaryToNyms: Map<string,string[]>, block: number, isFinalState: boolean) {
+ console.log("dumpNyms:", description);
+ console.log("Nym vote info for block", block);
+ let balTotalAll = BigNumber.from(0);
+ let priorBalTotal = BigNumber.from(-1);
+ let priorVoteTotal = BigNumber.from(-1);
+ for (let key of primaryToNyms.keys()) {
+ console.log(" " + key + "'s nym info:")
+ let value = primaryToNyms.get(key);
+ if (!value) continue;
+ let balTotal = BigNumber.from(0);
+ let voteTotal = BigNumber.from(0);
+ for (let nymName of value) {
+ let nym = names.get(nymName)
+ if (!nym) continue;
+ let bal = await fdtMock.balanceOf(nym.address);
+ let vote = await ve.balanceOfAt(nym.address, block);
+ console.log(" Name:", nymName, " (", nym.address, ")",
+ "\n Balance:", bal.toString(),
+ "\n Votes:", vote.toString())
+ balTotal = balTotal.add(bal);
+ voteTotal = voteTotal.add(vote);
+ }
+ console.log(" Total nyms balance:", balTotal.toString(), "Total votes:", voteTotal.toString());
+ balTotalAll = balTotalAll.add(balTotal);
+ if (!priorBalTotal.eq(BigNumber.from(-1))) {
+ expect(priorBalTotal.sub(balTotal)).to.below(1);
+ if (isFinalState) {
+ // test must always be arranged in order of decreasing nym splits for the
+ // following condition to pass (so that larger splits are confirmed to be
+ // more expensive than smaller ones)
+ expect(voteTotal.sub(priorVoteTotal)).to.below(1);
+ }
+ }
+ priorBalTotal = balTotal;
+ priorVoteTotal = voteTotal;
+ }
+ console.log("\n All account total balance:", balTotalAll.toString());
+ let veBal = await fdtMock.balanceOf(ve.address);
+ console.log(" Balance of ve:", veBal.toString());
+ console.log(" Sum:", veBal.add(balTotalAll).toString());
+ }
+
before(async function () {
await createSnapshot(provider);
@@ -115,6 +158,105 @@ describe("VotingEscrow Tests", function () {
await restoreSnapshot(provider);
});
+
+ // to run:
+ // rm -Rf 2022-08-fiatdao || true && git clone https://github.com/code-423n4/2022-08-fiatdao && cd 2022-08-fiatdao && npm install && npm run build && wget https://gist.githubusercontent.com/IllIllI000/63e170b9a07a321ceec79938ac804aa5/raw/a28539747166b03c74a3bd7e398a08466cadba93/veFDT_mit_nym.diff && git apply veFDT_mit_nym.diff && npx hardhat test --config hardhat.config.test.ts test/votingEscrowTest.ts
+
+
+ describe("IllIllI Mitigation tests", async () => {
+ it("IllIllI - Ensure lots of small delegations are equal to one large one", async () => {
+ //await createSnapshot(provider);
+ const lockTime = 1 * WEEK + (await getTimestamp());
+
+ let names = new Map();
+ names.set('alice', alice);
+ names.set('bob', bob);
+ names.set('charlie', charlie);
+ names.set('david', david);
+ names.set('eve', eve);
+ names.set('contract', contract);
+ names.set('ve', ve);
+
+ let primaryToNyms = new Map();
+ primaryToNyms.set('alice', [ 'alice', 'charlie', 'david' ]);
+ primaryToNyms.set('bob', [ 'bob', 'eve', 'contract' ]);
+
+ // pre lock balances
+ let block = await getBlock();
+ await dumpNyms("Initial state", names, primaryToNyms, block, false);
+
+ let tx1, tx2, tx3, tx4, tx5, resp1, resp2, resp3, resp4, resp5
+ await provider.send("evm_setAutomine", [false]);
+ await provider.send("evm_setIntervalMining", [0]);
+ await provider.send("evm_mine", []);
+
+ // alice creates a lot of small nym locks, but bob creates one
+
+ // +1 results in equality, ceil results in larger penalty for splitting, both larger for split
+ //let amountToLock = BigNumber.from("10000000000000000000");
+ // +1 results in larger penalty for splitting, ceil results in larger penalty for splitting, both larger for split
+ //let amountToLock = BigNumber.from("10000000000");
+ // +1 results in equality, ceil results in equality, both you can't quit
+ let amountToLock = BigNumber.from("1");
+
+ // In this test, since there are three splits for alice, but none for bob,
+ // if bob's left most penalty digit rounds up to three, and alice's
+ // each round up from zero to one, it's possible for rounding to cause bob's
+ // single penalty to equal alice's total penalty. Similarly it's possible
+ // for each of alice's fractions of a penalty to total less than one wei,
+ // but since they're each rounded separately, the over all penalty for
+ // alice is larger. Therefore, it's not possible to change the algorithm
+ // such that the penalty for splitting is always equal to the penalty for
+ // not splitting - the best one can do is to charge at _least_ as much
+ // for the split as for the non-split
+
+ tx1 = await ve.connect(alice).createLock(amountToLock, lockTime);
+ tx2 = await ve.connect(charlie).createLock(amountToLock, lockTime);
+ tx3 = await ve.connect(david).createLock(amountToLock, lockTime);
+ tx4 = await ve.connect(bob).createLock(amountToLock.mul(3), lockTime);
+ for (let i = 0; i < 10; ++i) await provider.send("evm_mine", []);
+
+ resp1 = await tx1.wait();
+ resp2 = await tx2.wait();
+ resp3 = await tx3.wait();
+ resp4 = await tx4.wait();
+ console.log(resp1.blockNumber, resp2.blockNumber, resp4.blockNumber, resp4.blockNumber);
+
+ // everyone extends their lock then quits
+ const lockTime2 = 50 * WEEK + (await getTimestamp());
+ tx1 = await ve.connect(alice).increaseUnlockTime(lockTime2);
+ tx2 = await ve.connect(bob).increaseUnlockTime(lockTime2);
+ tx3 = await ve.connect(charlie).increaseUnlockTime(lockTime2);
+ tx4 = await ve.connect(david).increaseUnlockTime(lockTime2);
+ for (let i = 0; i < 10; ++i) await provider.send("evm_mine", []);
+ resp1 = await tx1.wait();
+ resp2 = await tx2.wait();
+ resp3 = await tx3.wait();
+ resp4 = await tx4.wait();
+ console.log(resp1.blockNumber, resp2.blockNumber, resp3.blockNumber, resp4.blockNumber);
+ await dumpNyms("Everyone has extended", names, primaryToNyms, resp4.blockNumber, false);
+
+ // note that in some runs, this happens in the same block number, but one second later,
+ // causing penalties to change
+ tx1 = await ve.connect(alice).quitLock();
+ tx2 = await ve.connect(bob).quitLock();
+ tx3 = await ve.connect(charlie).quitLock();
+ tx4 = await ve.connect(david).quitLock();
+ for (let i = 0; i < 10; ++i) await provider.send("evm_mine", []);
+ resp1 = await tx1.wait();
+ resp2 = await tx2.wait();
+ resp3 = await tx3.wait();
+ resp4 = await tx4.wait();
+ console.log(resp1.blockNumber, resp2.blockNumber, resp3.blockNumber, resp4.blockNumber);
+
+ block = resp1.blockNumber;
+ await dumpNyms("Everyone has quit", names, primaryToNyms, block, true);
+
+ await provider.send("evm_setAutomine", [true]);
+ await provider.send("evm_setIntervalMining", [5000]);
+ });
+ });
+/**
describe("Deployment", async () => {
it("Initialized properly", async () => {
expect(await ve.owner()).to.equal(admin.address);
@@ -856,5 +998,5 @@ describe("VotingEscrow Tests", function () {
await ve.connect(alice).quitLock();
expect(await fdtMock.balanceOf(alice.address)).to.equal(aliceBalBefore);
});
- });
+ });/**/
});
diff --git a/tsconfig.json b/tsconfig.json
index a0e6c93..4100631 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -12,6 +12,7 @@
"typechain": ["./typechain"],
"typechain/*": ["./typechain/*"],
},
+ "downlevelIteration": true
},
"include": [
"./scripts",
@@ -19,4 +20,4 @@
"./typechain"
],
"files": ["./hardhat.config.ts", "./hardhat.config.test.ts"]
- }
\ No newline at end of file
+ }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment