Skip to content

add: malicious send calls #401

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
May 7, 2025
2 changes: 1 addition & 1 deletion src/components/ppom/batching.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ export function ppomMaliciousBatchingAndQueueing(parentContainer) {
params: [
{
from: globalContext.accounts[0],
to: '0x5FbDB2315678afecb367f032d93F642f64180aa3',
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove hardcoded malicious address, and use the const

to: maliciousAddress,
value: '0x0',
gasLimit: MIN_GAS_LIMIT,
maxFeePerGas: '0x2540be400',
Expand Down
219 changes: 219 additions & 0 deletions src/components/ppom/eip5792.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
import globalContext from '../..';
import { DEFAULT_CALLS } from '../transactions/eip5792/sendCalls';
import { getMaliciousTransactions } from './sharedConstants';

export function ppomMaliciousSendCalls(parentContainer) {
parentContainer.insertAdjacentHTML(
'beforeend',
`<div class="col-xl-4 col-lg-6 col-md-12 col-sm-12 col-12 d-flex align-items-stretch">
<div class="card full-width">
<div class="card-body">
<h4 class="card-title">
PPOM - EIP 5792 - Malicious Send Calls
</h4>
<button class="btn btn-primary btn-lg btn-block mb-3" id="ppomSendMaliciousEthButton">
Send Calls with Malicious ETH Transfer
</button>
<button class="btn btn-primary btn-lg btn-block mb-3" id="ppomSendMaliciousERC20TransferButton">
Send Calls with Malicious ERC20 Transfer (USDC)
</button>
<button class="btn btn-primary btn-lg btn-block mb-3" id="ppomSendMaliciousERC20ApprovalButton">
Send Calls with Malicious ERC20 Approval (BUSDC)
</button>
<button class="btn btn-primary btn-lg btn-block mb-3" id="ppomSendMaliciousSetApprovalForAllButton">
Send Calls with Malicious Set Approval for All
</button>
<button class="btn btn-primary btn-lg btn-block mb-3" id="ppomSendMaliciousContractInteractionButton">
Send Calls with Malicious Contract Interaction
</button>
<button class="btn btn-primary btn-lg btn-block mb-3" id="ppomSendThreeMaliciousTxsButton">
Send Calls with 3 Malicious Transactions
</button>
<hr/>
<div id="ppomRequestIdContainer" hidden>
<label>Request ID:</label>
<input type="text" id="ppomRequestIdInput" class="form-control" readonly />
</div>
<p class="info-text alert alert-warning" id="ppomSendCallsErrorContainer" hidden>
<span class="wrap" id="ppomSendCallsError"></span>
</p>
<button class="btn btn-primary btn-lg btn-block mb-3" id="ppomGetCallsStatusButton" disabled>
Get Calls Status
</button>
<p class="info-text alert alert-success">
<span class="wrap" id="ppomGetCallsStatusResult">Status</span>
</p>
</div>
</div>
</div>`,
);

const ppomSendMaliciousEthButton = document.getElementById(
'ppomSendMaliciousEthButton',
);

ppomSendMaliciousEthButton.onclick = async () => {
await sendMaliciousCalls('eth');
};

const ppomSendMaliciousERC20TransferButton = document.getElementById(
'ppomSendMaliciousERC20TransferButton',
);

ppomSendMaliciousERC20TransferButton.onclick = async () => {
await sendMaliciousCalls('erc20Transfer');
};

const ppomSendMaliciousERC20ApprovalButton = document.getElementById(
'ppomSendMaliciousERC20ApprovalButton',
);

ppomSendMaliciousERC20ApprovalButton.onclick = async () => {
await sendMaliciousCalls('erc20Approval');
};

const ppomSendMaliciousSetApprovalForAllButton = document.getElementById(
'ppomSendMaliciousSetApprovalForAllButton',
);

ppomSendMaliciousSetApprovalForAllButton.onclick = async () => {
await sendMaliciousCalls('setApprovalForAll');
};

const ppomSendMaliciousContractInteractionButton = document.getElementById(
'ppomSendMaliciousContractInteractionButton',
);

ppomSendMaliciousContractInteractionButton.onclick = async () => {
await sendMaliciousCalls('maliciousContractInteraction');
};

const ppomSendThreeMaliciousTxsButton = document.getElementById(
'ppomSendThreeMaliciousTxsButton',
);

ppomSendThreeMaliciousTxsButton.onclick = async () => {
await sendThreeMaliciousCalls();
};

document.addEventListener('globalConnectionChange', function (e) {
if (e.detail.connected) {
// MetaMask is connected, enable the button
ppomSendMaliciousEthButton.disabled = false;
ppomSendMaliciousERC20TransferButton.disabled = false;
ppomSendMaliciousERC20ApprovalButton.disabled = false;
ppomSendMaliciousSetApprovalForAllButton.disabled = false;
ppomSendMaliciousContractInteractionButton.disabled = false;
ppomSendThreeMaliciousTxsButton.disabled = false;
}
});

document.addEventListener('disableAndClear', function () {
ppomSendMaliciousEthButton.disabled = true;
ppomSendMaliciousERC20TransferButton.disabled = true;
ppomSendMaliciousERC20ApprovalButton.disabled = true;
ppomSendMaliciousSetApprovalForAllButton.disabled = true;
ppomSendMaliciousContractInteractionButton.disabled = true;
ppomSendThreeMaliciousTxsButton.disabled = true;
});

async function sendMaliciousCalls(type) {
const maliciousTransactions = getMaliciousTransactions(globalContext);
const calls = [];

switch (type) {
case 'eth':
calls.push(maliciousTransactions.eth);
break;
case 'erc20Transfer':
calls.push(maliciousTransactions.erc20Transfer);
break;
case 'erc20Approval':
calls.push(maliciousTransactions.erc20Approval);
break;
case 'maliciousContractInteraction':
calls.push(maliciousTransactions.maliciousContractInteraction);
break;
case 'setApprovalForAll':
calls.push(maliciousTransactions.setApprovalForAll);
break;
default:
// Do nothing
break;
}

calls.push(...DEFAULT_CALLS);

try {
const result = await globalContext.provider.request({
method: 'wallet_sendCalls',
params: [getParams(calls)],
});
document.getElementById('ppomRequestIdInput').value = result.id;
document.getElementById('ppomRequestIdContainer').hidden = false;
document.getElementById('ppomGetCallsStatusButton').disabled = false;
document.getElementById('ppomSendCallsErrorContainer').hidden = true;
} catch (error) {
console.error(error);
document.getElementById('ppomSendCallsErrorContainer').hidden = false;
document.getElementById(
'ppomSendCallsError',
).innerHTML = `Error: ${error.message}`;
}
}

async function sendThreeMaliciousCalls() {
const maliciousTransactions = getMaliciousTransactions(globalContext);

const calls = [
maliciousTransactions.erc20Approval,
maliciousTransactions.setApprovalForAll,
maliciousTransactions.maliciousContractInteraction,
];

try {
const result = await globalContext.provider.request({
method: 'wallet_sendCalls',
params: [getParams(calls)],
});
document.getElementById('ppomRequestIdInput').value = result.id;
document.getElementById('ppomRequestIdContainer').hidden = false;
document.getElementById('ppomGetCallsStatusButton').disabled = false;
document.getElementById('ppomSendCallsErrorContainer').hidden = true;
} catch (error) {
console.error(error);
document.getElementById('ppomSendCallsErrorContainer').hidden = false;
document.getElementById(
'ppomSendCallsError',
).innerHTML = `Error: ${error.message}`;
}
}

// Get Calls Status functionality
document.getElementById('ppomGetCallsStatusButton').onclick = async () => {
const requestId = document.getElementById('ppomRequestIdInput').value;
const resultOutput = document.getElementById('ppomGetCallsStatusResult');

try {
const result = await globalContext.provider.request({
method: 'wallet_getCallsStatus',
params: [requestId],
});

resultOutput.innerHTML = JSON.stringify(result, null, 2);
document.getElementById('ppomGetCallsStatusButton').disabled = false;
} catch (error) {
console.error(error);
resultOutput.innerHTML = `Error: ${error.message}`;
}
};

function getParams(calls) {
return {
version: '1.0',
from: globalContext.accounts[0],
chainId: `0x${globalContext.chainIdInt.toString(16)}`,
calls,
};
}
}
3 changes: 2 additions & 1 deletion src/components/ppom/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './transactions';
export * from './batching';
export * from './bypasses';
export * from './eip5792';
export * from './transactions';
41 changes: 41 additions & 0 deletions src/components/ppom/sharedConstants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { maliciousAddress } from '../../sample-addresses';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved the malicious tx's in this file, so they can be used both in the ppom tx and in the ppom batch txs

import {
ERC20_SAMPLE_CONTRACTS,
ERC721_SAMPLE_CONTRACTS,
MALICIOUS_CONTRACT_ADDRESSES,
NETWORKS_BY_CHAIN_ID,
} from '../../onchain-sample-contracts';

export const getMaliciousTransactions = (globalContext) => {
const chainId = globalContext.chainIdInt;
const networkName = NETWORKS_BY_CHAIN_ID[chainId] || 'default';

return {
eth: {
to: maliciousAddress,
value: '0x9184e72a000',
},
erc20Transfer: {
to: ERC20_SAMPLE_CONTRACTS[networkName],
data: '0xa9059cbb0000000000000000000000005fbdb2315678afecb367f032d93f642f64180aa30000000000000000000000000000000000000000000000000000000000000064',
value: '0x0',
},
erc20Approval: {
to: ERC20_SAMPLE_CONTRACTS[networkName],
data: '0x095ea7b3000000000000000000000000e50a2dbc466d01a34c3e8b7e8e45fce4f7da39e6000000000000000000000000000000000000000000000000ffffffffffffffff',
value: '0x0',
},
setApprovalForAll: {
to: ERC721_SAMPLE_CONTRACTS[networkName],
data: '0xa22cb465000000000000000000000000b85492afc686d5ca405e3cd4f50b05d358c75ede0000000000000000000000000000000000000000000000000000000000000001',
value: '0x0',
},
maliciousContractInteraction: {
to:
MALICIOUS_CONTRACT_ADDRESSES[networkName] ||
MALICIOUS_CONTRACT_ADDRESSES.default,
data: '0xef5cfb8c0000000000000000000000000b3e87a076ac4b0d1975f0f232444af6deb96c59',
value: '0x0',
},
};
};
Loading
Loading