Skip to content

Commit 57d3df4

Browse files
authored
add: malicious send calls (#401)
* malicious send calls * tweaks * remove comments * fix * text * add connections * tweaks * order * 3 malicious tx * add error section * disable/enable button * order alphabetically * malicious address * revert malicious address as its fixed * update version * address Ariella's commentoptimization
1 parent 554a788 commit 57d3df4

File tree

8 files changed

+312
-67
lines changed

8 files changed

+312
-67
lines changed

src/components/ppom/batching.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ export function ppomMaliciousBatchingAndQueueing(parentContainer) {
159159
params: [
160160
{
161161
from: globalContext.accounts[0],
162-
to: '0x5FbDB2315678afecb367f032d93F642f64180aa3',
162+
to: maliciousAddress,
163163
value: '0x0',
164164
gasLimit: MIN_GAS_LIMIT,
165165
maxFeePerGas: '0x2540be400',

src/components/ppom/eip5792.js

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
import globalContext from '../..';
2+
import { DEFAULT_CALLS, VERSION } from '../transactions/eip5792/sendCalls';
3+
import { getMaliciousTransactions } from './sharedConstants';
4+
5+
export function ppomMaliciousSendCalls(parentContainer) {
6+
parentContainer.insertAdjacentHTML(
7+
'beforeend',
8+
`<div class="col-xl-4 col-lg-6 col-md-12 col-sm-12 col-12 d-flex align-items-stretch">
9+
<div class="card full-width">
10+
<div class="card-body">
11+
<h4 class="card-title">
12+
PPOM - EIP 5792 - Malicious Send Calls
13+
</h4>
14+
<button class="btn btn-primary btn-lg btn-block mb-3" id="ppomSendMaliciousEthButton">
15+
Send Calls with Malicious ETH Transfer
16+
</button>
17+
<button class="btn btn-primary btn-lg btn-block mb-3" id="ppomSendMaliciousERC20TransferButton">
18+
Send Calls with Malicious ERC20 Transfer (USDC)
19+
</button>
20+
<button class="btn btn-primary btn-lg btn-block mb-3" id="ppomSendMaliciousERC20ApprovalButton">
21+
Send Calls with Malicious ERC20 Approval (BUSDC)
22+
</button>
23+
<button class="btn btn-primary btn-lg btn-block mb-3" id="ppomSendMaliciousSetApprovalForAllButton">
24+
Send Calls with Malicious Set Approval for All
25+
</button>
26+
<button class="btn btn-primary btn-lg btn-block mb-3" id="ppomSendMaliciousContractInteractionButton">
27+
Send Calls with Malicious Contract Interaction
28+
</button>
29+
<button class="btn btn-primary btn-lg btn-block mb-3" id="ppomSendThreeMaliciousTxsButton">
30+
Send Calls with 3 Malicious Transactions
31+
</button>
32+
<hr/>
33+
<div id="ppomRequestIdContainer" hidden>
34+
<label>Request ID:</label>
35+
<input type="text" id="ppomRequestIdInput" class="form-control" readonly />
36+
</div>
37+
<p class="info-text alert alert-warning" id="ppomSendCallsErrorContainer" hidden>
38+
<span class="wrap" id="ppomSendCallsError"></span>
39+
</p>
40+
<button class="btn btn-primary btn-lg btn-block mb-3" id="ppomGetCallsStatusButton" disabled>
41+
Get Calls Status
42+
</button>
43+
<p class="info-text alert alert-success">
44+
<span class="wrap" id="ppomGetCallsStatusResult">Status</span>
45+
</p>
46+
</div>
47+
</div>
48+
</div>`,
49+
);
50+
51+
const ppomSendMaliciousEthButton = document.getElementById(
52+
'ppomSendMaliciousEthButton',
53+
);
54+
55+
ppomSendMaliciousEthButton.onclick = async () => {
56+
await sendMaliciousCalls('eth');
57+
};
58+
59+
const ppomSendMaliciousERC20TransferButton = document.getElementById(
60+
'ppomSendMaliciousERC20TransferButton',
61+
);
62+
63+
ppomSendMaliciousERC20TransferButton.onclick = async () => {
64+
await sendMaliciousCalls('erc20Transfer');
65+
};
66+
67+
const ppomSendMaliciousERC20ApprovalButton = document.getElementById(
68+
'ppomSendMaliciousERC20ApprovalButton',
69+
);
70+
71+
ppomSendMaliciousERC20ApprovalButton.onclick = async () => {
72+
await sendMaliciousCalls('erc20Approval');
73+
};
74+
75+
const ppomSendMaliciousSetApprovalForAllButton = document.getElementById(
76+
'ppomSendMaliciousSetApprovalForAllButton',
77+
);
78+
79+
ppomSendMaliciousSetApprovalForAllButton.onclick = async () => {
80+
await sendMaliciousCalls('setApprovalForAll');
81+
};
82+
83+
const ppomSendMaliciousContractInteractionButton = document.getElementById(
84+
'ppomSendMaliciousContractInteractionButton',
85+
);
86+
87+
ppomSendMaliciousContractInteractionButton.onclick = async () => {
88+
await sendMaliciousCalls('maliciousContractInteraction');
89+
};
90+
91+
const ppomSendThreeMaliciousTxsButton = document.getElementById(
92+
'ppomSendThreeMaliciousTxsButton',
93+
);
94+
95+
ppomSendThreeMaliciousTxsButton.onclick = async () => {
96+
await sendThreeMaliciousCalls();
97+
};
98+
99+
document.addEventListener('globalConnectionChange', function (e) {
100+
if (e.detail.connected) {
101+
// MetaMask is connected, enable the button
102+
ppomSendMaliciousEthButton.disabled = false;
103+
ppomSendMaliciousERC20TransferButton.disabled = false;
104+
ppomSendMaliciousERC20ApprovalButton.disabled = false;
105+
ppomSendMaliciousSetApprovalForAllButton.disabled = false;
106+
ppomSendMaliciousContractInteractionButton.disabled = false;
107+
ppomSendThreeMaliciousTxsButton.disabled = false;
108+
}
109+
});
110+
111+
document.addEventListener('disableAndClear', function () {
112+
ppomSendMaliciousEthButton.disabled = true;
113+
ppomSendMaliciousERC20TransferButton.disabled = true;
114+
ppomSendMaliciousERC20ApprovalButton.disabled = true;
115+
ppomSendMaliciousSetApprovalForAllButton.disabled = true;
116+
ppomSendMaliciousContractInteractionButton.disabled = true;
117+
ppomSendThreeMaliciousTxsButton.disabled = true;
118+
});
119+
120+
async function sendMaliciousCalls(type) {
121+
const maliciousTransactions = getMaliciousTransactions(globalContext);
122+
const calls = [];
123+
124+
switch (type) {
125+
case 'eth':
126+
calls.push(maliciousTransactions.eth);
127+
break;
128+
case 'erc20Transfer':
129+
calls.push(maliciousTransactions.erc20Transfer);
130+
break;
131+
case 'erc20Approval':
132+
calls.push(maliciousTransactions.erc20Approval);
133+
break;
134+
case 'maliciousContractInteraction':
135+
calls.push(maliciousTransactions.maliciousContractInteraction);
136+
break;
137+
case 'setApprovalForAll':
138+
calls.push(maliciousTransactions.setApprovalForAll);
139+
break;
140+
default:
141+
// Do nothing
142+
break;
143+
}
144+
145+
calls.push(...DEFAULT_CALLS);
146+
147+
try {
148+
const result = await globalContext.provider.request({
149+
method: 'wallet_sendCalls',
150+
params: [getParams(calls)],
151+
});
152+
document.getElementById('ppomRequestIdInput').value = result.id;
153+
document.getElementById('ppomRequestIdContainer').hidden = false;
154+
document.getElementById('ppomGetCallsStatusButton').disabled = false;
155+
document.getElementById('ppomSendCallsErrorContainer').hidden = true;
156+
} catch (error) {
157+
console.error(error);
158+
document.getElementById('ppomSendCallsErrorContainer').hidden = false;
159+
document.getElementById(
160+
'ppomSendCallsError',
161+
).innerHTML = `Error: ${error.message}`;
162+
}
163+
}
164+
165+
async function sendThreeMaliciousCalls() {
166+
const maliciousTransactions = getMaliciousTransactions(globalContext);
167+
168+
const calls = [
169+
maliciousTransactions.erc20Approval,
170+
maliciousTransactions.setApprovalForAll,
171+
maliciousTransactions.maliciousContractInteraction,
172+
];
173+
174+
try {
175+
const result = await globalContext.provider.request({
176+
method: 'wallet_sendCalls',
177+
params: [getParams(calls)],
178+
});
179+
document.getElementById('ppomRequestIdInput').value = result.id;
180+
document.getElementById('ppomRequestIdContainer').hidden = false;
181+
document.getElementById('ppomGetCallsStatusButton').disabled = false;
182+
document.getElementById('ppomSendCallsErrorContainer').hidden = true;
183+
} catch (error) {
184+
console.error(error);
185+
document.getElementById('ppomSendCallsErrorContainer').hidden = false;
186+
document.getElementById(
187+
'ppomSendCallsError',
188+
).innerHTML = `Error: ${error.message}`;
189+
}
190+
}
191+
192+
// Get Calls Status functionality
193+
document.getElementById('ppomGetCallsStatusButton').onclick = async () => {
194+
const requestId = document.getElementById('ppomRequestIdInput').value;
195+
const resultOutput = document.getElementById('ppomGetCallsStatusResult');
196+
197+
try {
198+
const result = await globalContext.provider.request({
199+
method: 'wallet_getCallsStatus',
200+
params: [requestId],
201+
});
202+
203+
resultOutput.innerHTML = JSON.stringify(result, null, 2);
204+
document.getElementById('ppomGetCallsStatusButton').disabled = false;
205+
} catch (error) {
206+
console.error(error);
207+
resultOutput.innerHTML = `Error: ${error.message}`;
208+
}
209+
};
210+
211+
function getParams(calls) {
212+
return {
213+
version: VERSION,
214+
from: globalContext.accounts[0],
215+
chainId: `0x${globalContext.chainIdInt.toString(16)}`,
216+
atomicRequired: true,
217+
calls,
218+
};
219+
}
220+
}

src/components/ppom/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1-
export * from './transactions';
21
export * from './batching';
32
export * from './bypasses';
3+
export * from './eip5792';
4+
export * from './transactions';
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { maliciousAddress } from '../../sample-addresses';
2+
import {
3+
ERC20_SAMPLE_CONTRACTS,
4+
ERC721_SAMPLE_CONTRACTS,
5+
MALICIOUS_CONTRACT_ADDRESSES,
6+
NETWORKS_BY_CHAIN_ID,
7+
} from '../../onchain-sample-contracts';
8+
9+
const maliciousTransactionsCache = {};
10+
11+
export const getMaliciousTransactions = (globalContext) => {
12+
const chainId = globalContext.chainIdInt;
13+
const networkName = NETWORKS_BY_CHAIN_ID[chainId] || 'default';
14+
15+
// to avoid recalculating the tx object everytime if the chainId hasn't changed
16+
if (maliciousTransactionsCache[chainId]) {
17+
return maliciousTransactionsCache[chainId];
18+
}
19+
20+
const transactions = {
21+
eth: {
22+
to: maliciousAddress,
23+
value: '0x9184e72a000',
24+
},
25+
erc20Transfer: {
26+
to: ERC20_SAMPLE_CONTRACTS[networkName],
27+
data: '0xa9059cbb0000000000000000000000005fbdb2315678afecb367f032d93f642f64180aa30000000000000000000000000000000000000000000000000000000000000064',
28+
value: '0x0',
29+
},
30+
erc20Approval: {
31+
to: ERC20_SAMPLE_CONTRACTS[networkName],
32+
data: '0x095ea7b3000000000000000000000000e50a2dbc466d01a34c3e8b7e8e45fce4f7da39e6000000000000000000000000000000000000000000000000ffffffffffffffff',
33+
value: '0x0',
34+
},
35+
setApprovalForAll: {
36+
to: ERC721_SAMPLE_CONTRACTS[networkName],
37+
data: '0xa22cb465000000000000000000000000b85492afc686d5ca405e3cd4f50b05d358c75ede0000000000000000000000000000000000000000000000000000000000000001',
38+
value: '0x0',
39+
},
40+
maliciousContractInteraction: {
41+
to:
42+
MALICIOUS_CONTRACT_ADDRESSES[networkName] ||
43+
MALICIOUS_CONTRACT_ADDRESSES.default,
44+
data: '0xef5cfb8c0000000000000000000000000b3e87a076ac4b0d1975f0f232444af6deb96c59',
45+
value: '0x0',
46+
},
47+
};
48+
49+
maliciousTransactionsCache[chainId] = transactions;
50+
return transactions;
51+
};

0 commit comments

Comments
 (0)