Skip to content

Commit

Permalink
Introduce a simulation task using Alchemy (#731)
Browse files Browse the repository at this point in the history
* simulation task using alchemy

* update lockfile

---------

Co-authored-by: amiecorso <[email protected]>
  • Loading branch information
amiecorso and amiecorso authored Mar 19, 2024
1 parent bca0fda commit 3373c00
Show file tree
Hide file tree
Showing 5 changed files with 209 additions and 4 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"@types/proper-lockfile": "^4.1.2",
"@types/sinon": "^10.0.13",
"@types/sinon-chai": "^3.2.9",
"alchemy-sdk": "^3.1.2",
"chai": "^4.3.7",
"chai-as-promised": "^7.1.1",
"chalk": "^4.0",
Expand Down
2 changes: 2 additions & 0 deletions tasks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { GET_LIST_MIGRATED_REMOVALS_TASK } from './list-remaining-migrated-remov
import { TASK as FORCE_UPGRADE_TASK } from './force-ugrade';
import { TASK as SIGN_MESSAGE_TASK } from './sign-message';
import { TASK as TEST_SIGN_TYPED_TASK } from './test-sign-typed';
import { GET_SIMULATE_TXN_TASK } from './simulate-txn-alchemy';

export interface Task {
run: ActionType<
Expand Down Expand Up @@ -88,4 +89,5 @@ export const TASKS = {
[FORCE_UPGRADE_TASK.name]: { ...FORCE_UPGRADE_TASK },
[SIGN_MESSAGE_TASK.name]: { ...SIGN_MESSAGE_TASK },
[TEST_SIGN_TYPED_TASK.name]: { ...TEST_SIGN_TYPED_TASK },
[GET_SIMULATE_TXN_TASK().name]: { ...GET_SIMULATE_TXN_TASK() },
} as const;
157 changes: 157 additions & 0 deletions tasks/simulate-txn-alchemy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/* eslint-disable no-await-in-loop -- need to submit transactions synchronously to avoid nonce collisions */

import { BigNumber, FixedNumber } from 'ethers';
import { task } from 'hardhat/config';

import { getLogger } from '@/utils/log';
import { getMarket, getRemoval } from '@/utils/contracts';
import { Alchemy, Network, Utils } from 'alchemy-sdk';

export const GET_SIMULATE_TXN_TASK = () =>
({
name: 'simulate-txn',
description: 'Utility to simulate a transaction with the Alchemy API',
run: async (
options: {},
_: CustomHardHatRuntimeEnvironment
): Promise<void> => {
const logger = getLogger({
prefix: undefined,
hre,
});
const network = hre.network.name;
if (![`localhost`, `mumbai`, `polygon`].includes(network)) {
throw new Error(
`Network ${network} is not supported. Please use localhost, mumbai, or polygon.`
);
}
const [signer] = await hre.getSigners();
const signerAddress = await signer.getAddress();

const settings = {
apiKey: process.env.ALCHEMY_API_KEY,
network: Network.MATIC_MAINNET,
};

const alchemy = new Alchemy(settings);

const marketContract = await getMarket({
hre,
signer,
});
const removalContract = await getRemoval({
hre,
signer,
});
console.log('MARKET CONTRACT ADDRESS', marketContract.address);

const polygonRelayerAddress =
'0x6fcF5C3E43bE33F4B14BB25B550adb6887C1E48c';

const marketBalance = await removalContract.getMarketBalance();
const marketBalanceInEth = FixedNumber.fromValue(marketBalance, 18);
console.log(
'CURRENT MARKET BALANCE (TONNES): ',
marketBalanceInEth.toString()
);

const hasRole = await marketContract.hasRole(
marketContract.MARKET_ADMIN_ROLE(),
polygonRelayerAddress
);
console.log('RELAYER HAS `MARKET_ADMIN_ROLE`? ', hasRole);

const latestBlock = await hre.ethers.provider.getBlock('latest');
const latestBlockGasLimit = Utils.hexStripZeros(
latestBlock.gasLimit.toHexString()
);
const latestFastGasPrice = await hre.ethers.provider.getGasPrice();
const fastGasPriceHexString = Utils.hexStripZeros(
latestFastGasPrice.toHexString()
);
console.log('LATEST BLOCK GAS LIMIT: ', latestBlockGasLimit);
console.log('LATEST FAST GAS PRICE: ', fastGasPriceHexString);

const purchaseAmountEth = 9_000;
const purchaseAmountWei = ethers.utils.parseUnits(
purchaseAmountEth.toString(),
18
);
console.log('PURCHASE AMOUNT (ETH): ', purchaseAmountEth);
console.log('PURCHASE AMOUNT (WEI): ', purchaseAmountWei);
const gasEstimation =
await marketContract.estimateGas.swapWithoutFeeSpecialOrder(
signerAddress, // recipient
polygonRelayerAddress, // purchaser (doesn't matter if they have USDC the price is 0)
purchaseAmountWei,
0,
0,
ethers.constants.AddressZero,
[]
);
console.log('GAS ESTIMATION', gasEstimation);

const transactionData = marketContract.interface.encodeFunctionData(
'swapWithoutFeeSpecialOrder',
[
signerAddress, // recipient
polygonRelayerAddress, // purchaser (doesn't matter if they have USDC the price is 0)
purchaseAmountWei,
0,
0,
ethers.constants.AddressZero,
[],
]
);

const transactionInformation = {
/** The address the transaction is directed to. */
to: marketContract.address,
/** The address the transaction is sent from. (This is what's spoofed) */
from: polygonRelayerAddress,
/** The gas provided for the transaction execution, as a hex string. */
gas: latestBlockGasLimit,
// gas: '0x1e8480', // 2,000,000
// gas: '0x1312D00', // 20,000,000
/** The gas price to use as a hex string. */
gasPrice: fastGasPriceHexString,
/** The value associated with the transaction as a hex string. */
value: '0x0',
/** The data associated with the transaction. */
data: transactionData,
};

const alchemyGasEstimation = await alchemy.transact.estimateGas(
transactionInformation
);
console.log('ALCHEMY GAS ESTIMATION', alchemyGasEstimation.toString());

const response = await alchemy.transact.simulateExecution(
transactionInformation
);

// const response = await alchemy.transact.simulateAssetChanges({
// /** The address the transaction is directed to. */
// to: marketContract.address,
// /** The address the transaction is sent from. (This is what's spoofed) */
// from: polygonRelayerAddress,
// /** The gas provided for the transaction execution, as a hex string. */
// // gas: latestBlockGasLimit,
// // gas: '0x1e8480', // 2,000,000
// gas: '0x1312D00', // 20,000,000
// /** The gas price to use as a hex string. */
// gasPrice: fastGasPriceHexString,
// /** The value associated with the transaction as a hex string. */
// value: '0x0',
// /** The data associated with the transaction. */
// data: transactionData,
// });

console.log('RESPONSE', response);
},
} as const);

(() => {
const { name, description, run } = GET_SIMULATE_TXN_TASK();
task(name, description, run);
})();
1 change: 1 addition & 0 deletions types/node/process.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
declare namespace NodeJS {
interface ProcessEnv {
MNEMONIC?: string;
ALCHEMY_API_KEY?: string;
ETHERNAL_EMAIL?: string;
ETHERNAL_PASSWORD?: string;
ETHERNAL: boolean;
Expand Down
52 changes: 48 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@
dependencies:
"@ethersproject/bignumber" "^5.6.2"

"@ethersproject/[email protected]":
"@ethersproject/[email protected]", "@ethersproject/contracts@^5.7.0":
version "5.7.0"
resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e"
integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==
Expand Down Expand Up @@ -716,7 +716,7 @@
dependencies:
"@ethersproject/logger" "^5.6.0"

"@ethersproject/[email protected]", "@ethersproject/providers@^5.7.1", "@ethersproject/providers@^5.7.2":
"@ethersproject/[email protected]", "@ethersproject/providers@^5.7.0", "@ethersproject/providers@^5.7.1", "@ethersproject/providers@^5.7.2":
version "5.7.2"
resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb"
integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==
Expand Down Expand Up @@ -903,7 +903,7 @@
"@ethersproject/constants" "^5.7.0"
"@ethersproject/logger" "^5.7.0"

"@ethersproject/[email protected]":
"@ethersproject/[email protected]", "@ethersproject/wallet@^5.7.0":
version "5.7.0"
resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d"
integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==
Expand Down Expand Up @@ -3380,6 +3380,26 @@ ajv@^8.0.0, ajv@^8.0.1, ajv@^8.6.3:
require-from-string "^2.0.2"
uri-js "^4.2.2"

alchemy-sdk@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/alchemy-sdk/-/alchemy-sdk-3.1.2.tgz#0808aeed7fcbbed9c516021ce9d4aa0e33e5ccf9"
integrity sha512-xpCgQRLektp6imKdGdHyuVHvbMGpaSe22+qvg9jjGx0Wwkh0XgPzSfKwAzFDlkCGMMdazhKCsHu22XP0xh1noQ==
dependencies:
"@ethersproject/abi" "^5.7.0"
"@ethersproject/abstract-provider" "^5.7.0"
"@ethersproject/bignumber" "^5.7.0"
"@ethersproject/bytes" "^5.7.0"
"@ethersproject/contracts" "^5.7.0"
"@ethersproject/hash" "^5.7.0"
"@ethersproject/networks" "^5.7.0"
"@ethersproject/providers" "^5.7.0"
"@ethersproject/units" "^5.7.0"
"@ethersproject/wallet" "^5.7.0"
"@ethersproject/web" "^5.7.0"
axios "^1.6.5"
sturdy-websocket "^0.2.1"
websocket "^1.0.34"

amazon-cognito-identity-js@^6.0.1:
version "6.1.2"
resolved "https://registry.yarnpkg.com/amazon-cognito-identity-js/-/amazon-cognito-identity-js-6.1.2.tgz#975df21b0590098c2d3f455f48dbba255560bbf5"
Expand Down Expand Up @@ -3869,6 +3889,15 @@ axios@^0.27.2:
follow-redirects "^1.14.9"
form-data "^4.0.0"

axios@^1.6.5:
version "1.6.7"
resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.7.tgz#7b48c2e27c96f9c68a2f8f31e2ab19f59b06b0a7"
integrity sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==
dependencies:
follow-redirects "^1.15.4"
form-data "^4.0.0"
proxy-from-env "^1.1.0"

axobject-query@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be"
Expand Down Expand Up @@ -8200,6 +8229,11 @@ follow-redirects@^1.14.9:
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==

follow-redirects@^1.15.4:
version "1.15.5"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.5.tgz#54d4d6d062c0fa7d9d17feb008461550e3ba8020"
integrity sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==

for-each@^0.3.3, for-each@~0.3.3:
version "0.3.3"
resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e"
Expand Down Expand Up @@ -12926,6 +12960,11 @@ proxy-addr@~2.0.7:
forwarded "0.2.0"
ipaddr.js "1.9.1"

proxy-from-env@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==

prr@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
Expand Down Expand Up @@ -15152,6 +15191,11 @@ strip-json-comments@~2.0.1:
resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==

sturdy-websocket@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/sturdy-websocket/-/sturdy-websocket-0.2.1.tgz#20a58fd53372ef96eaa08f3c61c91a10b07c7c05"
integrity sha512-NnzSOEKyv4I83qbuKw9ROtJrrT6Z/Xt7I0HiP/e6H6GnpeTDvzwGIGeJ8slai+VwODSHQDooW2CAilJwT9SpRg==

[email protected]:
version "8.1.1"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
Expand Down Expand Up @@ -17172,7 +17216,7 @@ [email protected]:
utf-8-validate "^5.0.2"
yaeti "^0.0.6"

websocket@^1.0.31, websocket@^1.0.32:
websocket@^1.0.31, websocket@^1.0.32, websocket@^1.0.34:
version "1.0.34"
resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.34.tgz#2bdc2602c08bf2c82253b730655c0ef7dcab3111"
integrity sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ==
Expand Down

0 comments on commit 3373c00

Please sign in to comment.