diff --git a/backend/.env.example b/backend/.env.example index 5d6ff47..0f1573e 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -11,6 +11,7 @@ FEE_MARKUP=10 HMAC_SECRET="" EPV_06=0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789,0x48e60BBb664aEfAc9f14aDB42e5FB5b4a119EB66 EPV_07=0x0000000071727De22E5E9d8BAf0edAc6f37da032 +EPV_08=0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108 # postgres database connection DATABASE_URL="postgresql://arkauser:paymaster@localhost:5432/arkadev" diff --git a/backend/CHANGELOG.md b/backend/CHANGELOG.md index 0167e1d..db9a0f9 100644 --- a/backend/CHANGELOG.md +++ b/backend/CHANGELOG.md @@ -1,4 +1,16 @@ # Changelog +## [4.0.1] - 2025-04-22 +### Fixes +- Removed 'entryPoint' params from `getAllCommonERC20PaymasterAddress` + +## [4.0.0] - 2025-04-01 +### New +- Added EPV08 Support + +## [3.1.7] - 2025-04-16 +### New +- Added support for multiTokenPaymaster deployed for EntryPoint v07 + ## [3.1.6] - 2025-04-02 ### Fixes - Fixed bug in paymaster estimation for multiTokenPaymaster getERC20Quotes API diff --git a/backend/config.json.default b/backend/config.json.default index 621d4b5..95a90e5 100644 --- a/backend/config.json.default +++ b/backend/config.json.default @@ -468,5 +468,15 @@ "thresholdValue": "0.016", "MultiTokenPaymasterOracleUsed": "chainlink", "entryPoint": "0x0000000071727De22E5E9d8BAf0edAc6f37da032" + }, + { + "chainId": 11155111, + "bundler": "https://testnet-rpc.etherspot.io/v3/11155111", + "contracts": { + "etherspotPaymasterAddress": "0xEd5371296A2030F53298a18a3Eb828cFc3dca73f" + }, + "thresholdValue": "0.016", + "MultiTokenPaymasterOracleUsed": "chainlink", + "entryPoint": "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108" } ] diff --git a/backend/migrations/2025032800001-update-apiKey-table.cjs b/backend/migrations/2025032800001-update-apiKey-table.cjs new file mode 100644 index 0000000..f6a78e2 --- /dev/null +++ b/backend/migrations/2025032800001-update-apiKey-table.cjs @@ -0,0 +1,27 @@ +require('dotenv').config(); +const { DataTypes, TEXT } = require('sequelize'); + +async function up({ context: queryInterface }) { + await queryInterface.addColumn( + {schema: process.env.DATABASE_SCHEMA_NAME, tableName: 'api_keys'}, + 'VERIFYING_PAYMASTERS_V3', + { + type: DataTypes.TEXT, + allowNull: true + } + ); +} + +async function down({ context: queryInterface }) { + await queryInterface.removeColumn( + {schema: process.env.DATABASE_SCHEMA_NAME, tableName: 'api_keys'}, + 'VERIFYING_PAYMASTERS_V3', + { + type: DataTypes.TEXT, + allowNull: true + } + ); +} + +/** @type {import('sequelize-cli').Migration} */ +module.exports = {up, down}; diff --git a/backend/migrations/2025032800002-update-arka-whitelist-table.cjs b/backend/migrations/2025032800002-update-arka-whitelist-table.cjs new file mode 100644 index 0000000..3ce4ddf --- /dev/null +++ b/backend/migrations/2025032800002-update-arka-whitelist-table.cjs @@ -0,0 +1,27 @@ +require('dotenv').config(); +const { DataTypes } = require('sequelize'); + +async function up({ context: queryInterface }) { + await queryInterface.addColumn( + {schema: process.env.DATABASE_SCHEMA_NAME, tableName: 'arka_whitelist'}, + 'EP_VERSION', + { + type: DataTypes.STRING, + allowNull: true + } + ); +} + +async function down({ context: queryInterface }) { + await queryInterface.removeColumn( + {schema: process.env.DATABASE_SCHEMA_NAME, tableName: 'arka_whitelist'}, + 'EP_VERSION', + { + type: DataTypes.STRING, + allowNull: true + } + ); +} + +/** @type {import('sequelize-cli').Migration} */ +module.exports = {up, down}; diff --git a/backend/migrations/20250416000001-update-apiKey-table.cjs b/backend/migrations/20250416000001-update-apiKey-table.cjs new file mode 100644 index 0000000..653c3ac --- /dev/null +++ b/backend/migrations/20250416000001-update-apiKey-table.cjs @@ -0,0 +1,11 @@ +require('dotenv').config(); + +async function up({ context: queryInterface }) { + await queryInterface.sequelize.query(`ALTER TABLE IF EXISTS "${process.env.DATABASE_SCHEMA_NAME}".api_keys ADD COLUMN "MULTI_TOKEN_PAYMASTERS_V2" text default null`); +} + +async function down({ context: queryInterface }) { + await queryInterface.sequelize.query(`ALTER TABLE IF EXISTS "${process.env.DATABASE_SCHEMA_NAME}".api_keys DROP COLUMN MULTI_TOKEN_PAYMASTERS_V2;`); +} + +module.exports = { up, down } \ No newline at end of file diff --git a/backend/migrations/20250416000002-update-MTP-table.cjs b/backend/migrations/20250416000002-update-MTP-table.cjs new file mode 100644 index 0000000..f5a2322 --- /dev/null +++ b/backend/migrations/20250416000002-update-MTP-table.cjs @@ -0,0 +1,11 @@ +require('dotenv').config(); + +async function up({ context: queryInterface }) { + await queryInterface.sequelize.query(`ALTER TABLE IF EXISTS "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ADD COLUMN "EP_VERSION" text default 'EPV_06'`); +} + +async function down({ context: queryInterface }) { + await queryInterface.sequelize.query(`ALTER TABLE "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster DROP COLUMN EP_VERSION;`); +} + +module.exports = { up, down } \ No newline at end of file diff --git a/backend/migrations/2025042200001-seed-data.cjs b/backend/migrations/2025042200001-seed-data.cjs new file mode 100644 index 0000000..ffe45cc --- /dev/null +++ b/backend/migrations/2025042200001-seed-data.cjs @@ -0,0 +1,203 @@ +require('dotenv').config(); + +async function up({ context: queryInterface }) { + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x8dBa75e83DA73cc766A7e5a0ee71F656BAb470d6', 10, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x94b008aA00579c1307B0EF2c499aD98a8ce58e58', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xECef79E109e997bCA29c1c0897ec9d7b03647F5E', 10, 6, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x68f180fcCe6836688e9084f035309E29Bf0A2095', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x718A5788b89454aAE3A028AE9c111A29Be6c2a6F', 10, 8, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x16a9FA2FDa030272Ce99B29CF780dFA30361E0f3', 10, 6, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x2FCF37343e916eAEd1f1DdaaF84458a359b53877', 10, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xCc232dcFAAE6354cE191Bd574108c1aD03f86450', 10, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x9e1028F5F1D5eDE59748FFceE5532509976840E0', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xA12CDDd8e986AF9288ab31E58C60e65F2987fB13', 10, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x4200000000000000000000000000000000000042', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x0D276FC14719f9292D5C1eA2198673d1f4269246', 10, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x3c8B650257cFb5f272f799F5e2b4e65093a11a05', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x0f2Ed59657e391746C1a097BDa98F2aBb94b1120', 10, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x9Bcef72be871e61ED4fBbc7630889beE758eb81D', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xb429DE60943a8e6DeD356dca2F93Cd31201D9ed0', 10, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x7F5c764cBc14f9669B88837ca1490cCa17c31607', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x16a9FA2FDa030272Ce99B29CF780dFA30361E0f3', 10, 6, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 10, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x1F32b1c2345538c0c6f582fCB022739c4A194Ebb', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 10, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x4200000000000000000000000000000000000006', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 10, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x217D47011b23BB961eB6D93cA9945B7501a5BB11', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 10, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 10, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x8aE125E8653821E851F12A49F7765db9a9ce7384', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 10, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x920Cf626a271321C151D027030D5d08aF699456b', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 10, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xdFA46478F9e5EA86d57387849598dbFB2e964b02', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 10, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x55d398326f99059fF775485246999027B3197955', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xB97Ad0E74fa7d920791E90258A6E2085088b4320', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xB6064eD41d4f67e353768aA239cA86f4F73665a1', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x2170Ed0880ac9A755fd29B2688956BD959F933F8', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x9ef1B8c0E4F7dc8bF5719Ea496883DC6401d5b2e', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x51597f405303C4377E36123cBc172b13269EA163', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x132d3C0B1D2cEa0BC552588063bdBb210FDeecfA', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x1D2F0da169ceB9fC7B3144628dB156f3F6c60dBE', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x93A67D414896A280bF8FFB3b389fE3686E014fda', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x14016E85a25aeb13065688cAFB43044C2ef86784', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xa3334A9762090E827413A7495AfeCE76F41dFc06', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xCC42724C6683B7E57334c4E856f4c9965ED682bD', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x7CA57b0cA6367191c94C8914d7Df09A57655905f', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xBf5140A22578168FD562DCcF235E5D43A02ce9B1', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xb57f259E7C24e56a1dA00F66b55A5640d9f9E7e4', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xF8A0BF9cF54Bb92F17374d9e9A321E6a111a51bD', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xca236E327F629f9Fc2c30A4E95775EbF0B89fac8', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xf7DE7E8A6bd59ED41a4b5fe50278b3B7f31384dF', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x20123C6ebd45c6496102BeEA86e1a6616Ca547c6', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x7Ddc52c4De30e94Be3A6A0A2b259b2850f421989', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x8b0D36ae4CF8e277773A7ba5F35c09Edb144241b', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xAD29AbB318791D579433D831ed122aFeAf29dcfe', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xe2A47e87C0f4134c8D06A41975F6860468b2F925', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xaEC945e04baF28b135Fa7c640f624f8D90F1C3a6', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x889158E39628C0397DC54B84F6b1cbe0AaEb7FFc', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x715D400F88C167884bbCc41C5FeA407ed4D2f8A0', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x7B49524ee5740c99435f52d731dFC94082fE61Ab', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x90C97F71E18723b0Cf0dfa30ee176Ab653E89F40', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x13A9c98b07F098c5319f4FF786eB16E22DC738e1', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x965F527D9159dCe6288a2219DB51fc6Eef120dD1', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x08E70777b982a58D23D05E3D7714f44837c06A21', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xfe56d5892BDffC7BF58f2E84BE1b2C32D21C308b', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xF2f8273F6b9Fc22C90891DC802cAf60eeF805cDF', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x4691937a7508860F876c9c0a2a617E7d9E945D4B', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x02Bfe714e78E2Ad1bb1C2beE93eC8dc5423B66d4', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x16939ef78684453bfDFb47825F8a5F714f12623a', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x9A18137ADCF7b05f033ad26968Ed5a9cf0Bf8E6b', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x8F0528cE5eF7B51152A59745bEfDD91D97091d2F', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xe0073b60833249ffd1bb2af809112c2fbf221DF6', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x762539b45A1dCcE3D36d080F74d1AED37844b878', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x38393201952f2764E04B290af9df427217D56B41', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x67ee3Cb086F8a16f34beE3ca72FAD36F7Db929e2', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x87701B15C08687341c2a847ca44eCfBc8d7873E1', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xFd7B3A77848f1C2D67E05E54d78d174a0C850335', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x887f177CBED2cf555a64e7bF125E1825EB69dB82', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x1Fa4a73a3F0133f0025378af00236f3aBDEE5D63', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x0Fe4D87883005fCAFaF56B81d09473D9A29dCDC3', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x0Eb3a705fc54725037CC9e008bDede697f62F335', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xb056B7C804297279A9a673289264c17E6Dc6055d', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x0D8Ce2A99Bb6e3B7Db580eD848240e4a0F9aE153', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xE5dbFD9003bFf9dF5feB2f4F445Ca00fb121fb83', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x8fF795a6F4D97E7887C79beA79aba5cc76444aDf', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x43d80f616DAf0b0B42a928EeD32147dC59027D41', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xb59490aB09A0f526Cc7305822aC65f2Ab12f9723', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x83766bA8d964fEAeD3819b145a69c947Df9Cb035', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x4338665CBB7B2485A8855A139b75D5e34AB0DB94', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x74E72F37A8c415c8f1a98Ed42E78Ff997435791D', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x56b6fB708fC5732DEC1Afc8D8556423A2EDcCbD6', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xd5508c8Ffdb8F15cE336e629fD4ca9AdB48f50F0', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xa2B726B1145A4773F68593CF171187d8EBe4d495', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x63A9133cd7c611d6049761038C16f238FddA71d7', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x52CE071Bd9b1C4B00A0b92D298c512478CaD67e8', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x0Db8945f9aEf5651fa5bd52314C5aAe78DfDe540', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x47BEAd2563dCBf3bF2c9407fEa4dC236fAbA485A', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xE188A9875af525d25334d75F3327863B2b8cd0F1', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x88f1A5ae2A3BF98AEAF342D26B30a79438c9142e', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xD7eAa5Bf3013A96e3d515c055Dbd98DbdC8c620D', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xcF6BB5389c92Bdda8a3747Ddb454cB7a64626C63', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xBF63F430A79D4036A5900C19818aFf1fa710f206', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x3EE2200Efb3400fAbB9AacF31297cBdD1d435D47', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xa767f745331D267c7751297D982b050c93985627', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xAD6cAEb32CD2c308980a548bD0Bc5AA4306c6c18', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xC78b99Ae87fF43535b0C782128DB3cB49c74A4d3', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x7083609fCE4d1d8Dc0C979AAb8c869Ea2C873402', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xC333eb0086309a16aa7c8308DfD32c8BBA0a2592', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x570A5D26f7765Ecb712C0924E4De545B89fD43dF', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x0E8a53DD9c13589df6382F13dA6B3Ec8F919B323', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xbA2aE424d960c26247Dd6c32edC70B295c744C43', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x3AB0A0d137D4F946fBB19eecc6e92E64660231C8', 56, 8, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x2eD9a5C8C13b93955103B9a7C167B67Ef4d568a3', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x4978c0abE6899178c1A74838Ee0062280888E2Cf', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x111111111117dC0aa78b770fA6A738034120C302', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x9a177Bb9f5b6083E962f9e62bD21d4b5660Aeb03', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x4B0F1812e5Df2A09796481Ff14017e6005508003', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x9C65AB58d8d978DB963e63f2bfB7121627e3a739', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xd17479997F34dd9156Deef8F95A52D81D265be9c', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xb86AbCb37C3A4B64f74f59301AFF131a1BEcC787', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 56, 12, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x3203c9E46cA618C8C1cE5dC67e7e9D75f5da2377', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x250632378E573c6Be1AC2f97Fcdf00515d0Aa91B', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xa1faa113cbE53436Df28FF0aEe54275c13B40975', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xF21768cCBC73Ea5B6fd3C687208a7c2def2d966e', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x4BD17003473389A42DAF6a0a729f6Fdb328BbBd7', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xa184088a740c695E156F91f5cC086a06bb78b827', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xfE19F0B51438fd612f6FD59C1dbB3eA319f433Ba', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x7130d2A12B9BCbFAe4f2634d864A1Ee1Ce3Ead9c', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x23396cF899Ca06c4472205fC903bDB4de249D6fC', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xD41FDb03Ba84762dD66a0af1a6C8540FF1ba5dfb', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xC9849E6fdB743d08fAeE3E34dd2D1bc69EA11a51', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xE02dF9e3e622DeBdD69fb838bB799E3F168902c5', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x603c7f932ED1fc6575303D8Fb018fDCBb0f39a95', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xf307910A4c7bbc79691fD374889b36d8531B08e3', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 56, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x4ECaBa5870353805a9F068101A40E0f32ed605C6', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x68811D7DF835B1c33e6EEae8E7C141eF48d48cc7', 100, 6, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x2a22f9c3b484c3629090FeED35F17Ff8F88f76F0', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x26C31ac71010aF62E6B486D1132E266D6298857D', 100, 6, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x8e5bBbb09Ed1ebdE8674Cda39A0c169401db4252', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x00288135bE38B83249F380e9b6b9a04c90EC39eE', 100, 8, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xE2e73A1c69ecF83F464EFCE6A5be353a37cA09b2', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xed322A5ac55BAE091190dFf9066760b86751947B', 100, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xDF613aF6B44a31299E48131e9347F034347E2F00', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x2b481Dc923Aa050E009113Dca8dcb0daB4B68cDF', 100, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x7eF541E2a22058048904fE5744f9c7E4C57AF717', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x1b723C855F7D2c2785F99486973271355e782d77', 100, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xDf6FF92bfDC1e8bE45177DC1f4845d391D3ad8fD', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xBa95Bc8418Ebcdf8a690924E1d4aD5292139F2EA', 100, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x712b3d230F3C1c19db860d80619288b1F0BDd0Bd', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xC77B83ac3Dd2a761073bD0f281f7b880B2DDDe18', 100, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xd7738ec74f08f3a14c478BBeCCe9c3F5603ba458', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x824b4A1A0443609A2ADd94a700b770FA5bE31287', 100, 8, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xe51Cf68301B30b06c72d38f5314FA85c94C8e5f1', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x3c30c5c415B2410326297F0f65f5Cbb32f3aefCc', 100, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xFAdc59D012Ba3c110B08A15B7755A5cb7Cbe77D7', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xeBbd67a84e33791F1bcFde74CDc22a71e332e2F1', 100, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x7ecF26cd9A36990b8ea477853663092333f59979', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x76e76F7E73F3BD42E3c2b4282B50b36E78130B4A', 100, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x3A00E08544d589E19a8e7D97D0294331341cdBF6', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x3b84d6e6976D5826500572600eB44f9f1753827b', 100, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x2995D1317DcD4f0aB89f4AE60F3f020A4F17C7CE', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xC0a6Bf8d5D408B091D022C3C0653d4056D4B9c01', 100, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x4537e328Bf7e4eFA29D05CAeA260D7fE26af9D74', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xd98735d78266c62277Bb4dBf3e3bCdd3694782F4', 100, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x7e860098F58bBFC8648a4311b374B1D669a2bc6B', 8453, 6, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x591e79239a7d679378eC8c847e5038150364C78F', 8453, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xd7818272B9e248357d13057AAb0B417aF31E817d', 8453, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x9EaF8C1E34F05a589EDa6BAfdF391Cf6Ad3CB239', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xD40e758b5eC80820B68DFC302fc5Ce1239083548', 8453, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xfA980cEd6895AC314E7dE34Ef1bFAE90a5AdD21b', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 8453, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xB6fe221Fe9EeF5aBa221c348bA20A1Bf5e73624c', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 8453, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xaf88d065e77c8cC2239327C5EDb3A432268e5831', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x50834F3163758fcC1Df9973b6e91f0F0F0434aD3', 42161, 6, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x50834F3163758fcC1Df9973b6e91f0F0F0434aD3', 42161, 6, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x3f3f5dF88dC9F13eac63DF89EC16ef6e7E25DdE7', 42161, 6, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xd0C7101eACbB49F3deCcCc166d238410D6D46d57', 42161, 8, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x912CE59144191C1204E64559FE8253a0e49E6548', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xb2A824043730FE05F3DA2efaFa1CBbe83fa548D6', 42161, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xfc5A1A6EB076a2C7aD06eD22C90d7E710E35ad0a', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xDB98056FecFff59D032aB628337A4887110df3dB', 42161, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xFa7F8980b0f1E64A2062791cc3b0871572f1F7f0', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x9C917083fDb403ab5ADbEC26Ee294f6EcAda2720', 42161, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x371c7ec6D8039ff7933a2AA28EB827Ffe1F52f07', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x04180965a782E487d0632013ABa488A472243542', 42161, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x040d1EdC9569d4Bab2D15287Dc5A4F10F56a56B8', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xBE5eA816870D11239c543F84b71439511D70B94f', 42161, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xf97f4df75117a78c1A5a0DBb814Af92458539FB4', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x86E53CF1B870786351Da77A57575e79CB55812CB', 42161, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xd4d42F0b6DEF4CE0383636770eF773390d85c61A', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xb2A8BA74cbca38508BA1632761b56C897060147C', 42161, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x639Fe6ab55C921f74e7fac1ee960C0B6293ba612', 42161, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x3E6648C5a70A150A88bCE65F4aD4d506Fe15d2AF', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x383b3624478124697BEF675F07cA37570b73992f', 42161, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x6694340fc020c5E6B96567843da2df01b2CE1eb6', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xe74d69E233faB0d8F48921f2D93aDfDe44cEb3B7', 42161, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x13Ad51ed4F1B7e9Dc168d8a00cB3f4dDD85EfA60', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xA43A34030088E6510FecCFb77E88ee5e7ed0fE64', 42161, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xEC70Dcb4A1EFa46b8F2D97C310C9c4790ba5ffA8', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xD6aB2298946840262FcC278fF31516D39fF611eF', 42161, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x3082CC23568eA640225c2467653dB90e9250AaA0', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x20d0Fcab0ECFD078B036b6CAf1FaC69A6453b352', 42161, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xc5C8E77B397E531B8EC06BFb0048328B30E9eCfB', 42161, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x5979D7b546E38E414F7E9822514be443A4800529', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 42161, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x6C2C06790b3E3E3c38e12Ee22F8183b37a13EE55', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 42161, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x93C15cd7DE26f07265f0272E0b831C5D7fAb174f', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 42161, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xFA5Ed56A203466CbBC2430a43c66b9D8723528E7', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 42161, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x4e352cF164E64ADCBad318C3a1e222E9EBa4Ce42', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 42161, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x51fC0f6660482Ea73330E414eFd7808811a57Fa2', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 42161, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xD74f5255D557944cf7Dd0E45FF521520002D5748', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 42161, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x088cd8f5eF3652623c22D48b1605DCfE860Cd704', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 42161, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x9ed7E4B1BFF939ad473dA5E7a218C771D1569456', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 42161, 6, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xC891EB4cbdEFf6e073e859e987815Ed1505c2ACD', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x3368310bC4AeE5D96486A73bae8E6b49FcDE62D3', 43114, 6, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xF096872672F44d6EBA71458D74fe67F9a77a23B9', 43114, 6, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xEBE676ee90Fe1112671f19b6B7459bC678B67e8a', 43114, 6, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xD24C2Ad096400B6FBcd2ad8B24E7acBc21A1da64', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xbBa56eF1565354217a3353a466edB82E8F25b08e', 43114, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xB3fe5374F67D7a22886A0eE082b2E2f9d2651651', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x49ccd9ca821EfEab2b98c60dC60F518E765EDe9a', 43114, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x8eBAf22B6F053dFFeaf46f4Dd9eFA95D89ba8580', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x9a1372f9b1B71B3A5a72E092AE67E172dBd7Daaa', 43114, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x62edc0692BD897D2295872a9FFCac5425011c661', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x3F968A21647d7ca81Fb8A5b69c0A452701d5DCe8', 43114, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x63a72806098Bd3D9520cC43356dD78afe5D386D9', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x3CA13391E9fb38a75330fb28f8cc2eB3D9ceceED', 43114, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x152b9d0FdC40C096757F570A51E494bd4b943E50', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x2779D32d5166BAaa2B2b658333bA7e6Ec0C65743', 43114, 8, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x98443B96EA4b0858FDF3219Cd13e98C7A4690588', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xe89B3CE86D25599D1e615C0f6a353B4572FF868D', 43114, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x62D0A8458eD7719FDAF978fe5929C6D342B0bFcE', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x3427232b88Ce4e7d62A03289247eE0cA5324f6ba', 43114, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x6e84a6216eA6dACC71eE8E6b0a5B7322EEbC0fDd', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x02D35d3a8aC3e1626d3eE09A78Dd87286F5E8e3a', 43114, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x976B3D034E162d8bD72D6b9C989d545b839003b0', 43114, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xd586E7F844cEa2F87f50152665BCbc2C279D8d70', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x51D7180edA2260cc4F6e4EebB82FEF5c3c2B8300', 43114, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x8729438EB15e2C8B576fCc6AeCdA6A148776C0F5', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x36E039e6391A5E7A7267650979fdf613f659be5D', 43114, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x249848BeCA43aC405b8102Ec90Dd5F22CA513c06', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x7CF8A6090A9053B01F3DF4D4e6CfEdd8c90d9027', 43114, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x39fC9e94Caeacb435842FADeDeCB783589F50f5f', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x9df2195dc96e6Ef983B1aAC275649F3f28F82Aa1', 43114, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x1C20E891Bab6b1727d14Da358FAe2984Ed9B59EB', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x9Cf3Ef104A973b351B2c032AA6793c3A6F76b448', 43114, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xfE4A8cc5b5B2366C1B58Bea3858e81843581b2F7', 137, 6, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xc2132D05D31c914a87C6611C10748AEb04B58e8F', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x0A6513e40db6EB1b165753AD52E80663aeA50545', 137, 6, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xD6DF932A45C0f255f85145f286eA0b292B21C90B', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x72484B12719E23115761D5DA1646945632979bB6', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x4746DeC9e833A82EC7C2C1356372CcF2cfcD2F3D', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xF9680D99D6C9589e2a93a78A04A279e509205945', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x53E0bca35eC356BD5ddDFebbD1Fc0fD03FaBad39', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xd9FFdb71EbE7496cC440152d43986Aae0AB76665', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xA1c57f48F0Deb89f569dFbE6E2B7f46D33606fD4', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xA1CbF3Fe43BC3501e3Fc4b573e822c70e76A7512', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xB5C064F955D8e7F38fE0460C556a72987494eE17', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x2251169D32E7538652a9a8c86bf0c43bFcd956f1', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xBbba073C31bF03b8ACf7c28EF0738DeCF3695683', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x3D49406EDd4D52Fb7FFd25485f32E073b529C924', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x0b3F868E0BE5597D5DB7fEB59E1CADBb0fdDa50a', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x49B0c695039243BBfEb8EcD054EB70061fd54aa0', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x2e1AD108fF1D8C782fcBbB89AAd783aC49586756', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x7C5D415B64312D38c56B54358449d0a4058339d2', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xb33EaAd8d922B1083446DC23f610c2567fB5180f', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xdf0Fb4e4F928d2dCB76f438575fDD8682386e13C', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xDE31F8bFBD8c84b5360CFACCa3539B938dd78ae6', 137, 8, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x9a71012B13CA4d3D0Cdc72A177DF3ef03b0E76A3', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xD106B538F2A868c28Ca1Ec7E298C3325E0251d66', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x172370d5Cd63279eFa6d502DAB29171933a610AF', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x336584C8E6Dc19637A5b36206B1c79923111b405', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x385Eeac5cB85A38A9a07A70c73e0a3271CfB54A7', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0xDD229Ce42f11D8Ee7fFf29bDB71C7b81352e11be', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xfa68FB4628DFF1028CFEc22b4162FCcd0d45efb6', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '0x5d37E4b374E6907de8Fc7fb33EE3b0af403C7403', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x229b1b6C23ff8953D663C4cBB519717e323a0a84', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x9C9e5fD8bbc25984B178FdCE6117Defa39d2db39', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xef938b6da8576a896f6E0321ef80996F4890f9c4', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xd99baFe5031cC8B345cb2e8c80135991F12D7130', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xE06Bd4F5aAc8D0aA337D13eC88dB6defC6eAEefE', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x4e3Decbb3645551B8A19f0eA1678079FCB33fB4c', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x4e78011Ce80ee02d2c3e649Fb657E45898257815', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 137, 9, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xC3C7d422809852031b44ab29EEC9F1EfF2A58756', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xEe9A352F6aAc4aF1A5B9f467F6a93E0ffBe9Dd35', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xee7666aACAEFaa6efeeF62ea40176d3eB21953B9', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xa3Fa99A148fA48D14Ed51d610c367C61876997F1', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x614389EaAE0A6821DC49062D56BDA3d9d45Fa2ff', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x42d61D766B85431666B39B89C43011f24451bFf6', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xC17c30e98541188614dF99239cABD40280810cA3', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x431CD3C9AC9Fc73644BF68bF5691f4B83F9E104f', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x1d734A02eF1e1f5886e66b0673b71Af5B53ffA94', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x62F594339830b90AE4C084aE7D223fFAFd9658A7', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x3A58a54C066FdC0f2D55FC9C89F0415C92eBf3C4', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xa1428174F516F527fafdD146b883bB4428682737', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xdF7837DE1F2Fa4631D716CF2502f8b230F1dcc32', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 137, 2, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x255707B70BF90aa112006E1b07B9AeA6De021424', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xd0258a3fD00f38aa8090dfee343f10A9D4d30D3F', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x82a0E6c02b91eC9f6ff943C0A933c03dBaa19689', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xDC3326e71D45186F113a2F448984CA0e8D201995', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 137, 6, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xC168E40227E4ebD8C1caE80F7a55a4F0e6D66C97', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 137, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x76FB31fb4af56892A25e32cFC43De717950c9278', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 10, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xd9aAEc86B65D86f6A7B5B1b0c42FFA531710b6CA', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 8453, 6, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0x17FC002b466eEc40DaE837Fc4bE5c67993ddBd6F', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 42161, 18, NOW(), NOW(), 'EPV_07')`); + await queryInterface.sequelize.query(`INSERT INTO "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster ("TOKEN_ADDRESS", "PAYMASTER_ADDRESS", "ORACLE_ADDRESS", "CHAIN_ID", "DECIMALS", "CREATED_AT", "UPDATED_AT", "EP_VERSION") VALUES ('0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83', '0x5E6ce32Bb6Fa47001cf87f2f9E07d5Fd3dE57990', '', 100, 6, NOW(), NOW(), 'EPV_07')`); +} + +async function down({ context: queryInterface }) { + await queryInterface.sequelize.query(`DELETE IF EXISTS FROM "${process.env.DATABASE_SCHEMA_NAME}".multi_token_paymaster;`); +} + +module.exports = { up, down } diff --git a/backend/package.json b/backend/package.json index e79a92e..8ba6424 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "arka", - "version": "3.1.6", + "version": "4.0.1", "description": "ARKA - (Albanian for Cashier's case) is the first open source Paymaster as a service software", "type": "module", "directories": { diff --git a/backend/src/abi/PimlicoAbi.ts b/backend/src/abi/ERC20PaymasterAbi.ts similarity index 100% rename from backend/src/abi/PimlicoAbi.ts rename to backend/src/abi/ERC20PaymasterAbi.ts diff --git a/backend/src/abi/MultiTokenPaymasterAbiV2.ts b/backend/src/abi/MultiTokenPaymasterAbiV2.ts new file mode 100644 index 0000000..4cdbbe8 --- /dev/null +++ b/backend/src/abi/MultiTokenPaymasterAbiV2.ts @@ -0,0 +1,878 @@ +export default [ + { + "inputs": [ + { + "internalType": "contract IEntryPoint", + "name": "_entryPoint", + "type": "address" + }, + { + "internalType": "address", + "name": "_verifyingSigner", + "type": "address" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "inputs": [], + "name": "CanNotWithdrawToZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "CannotBeUnrealisticValue", + "type": "error" + }, + { + "inputs": [], + "name": "DEXRouterCannotBeZero", + "type": "error" + }, + { + "inputs": [], + "name": "DepositCanNotBeZero", + "type": "error" + }, + { + "inputs": [], + "name": "ECDSAInvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "ECDSAInvalidSignatureLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "ECDSAInvalidSignatureS", + "type": "error" + }, + { + "inputs": [], + "name": "EntryPointCannotBeZero", + "type": "error" + }, + { + "inputs": [], + "name": "FeeReceiverCannotBeZero", + "type": "error" + }, + { + "inputs": [], + "name": "NativeTokenBalanceZero", + "type": "error" + }, + { + "inputs": [], + "name": "NativeTokensWithdrawalFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "OwnerCannotBeZero", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrancyGuardReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "TokensAndAmountsLengthMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "VerifyingSignerCannotBeZero", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "_oldThresholdCost", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "_newThresholdCost", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "_actor", + "type": "address" + } + ], + "name": "EPGasThresholdChange", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_oldfeeReceiver", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_newfeeReceiver", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_actor", + "type": "address" + } + ], + "name": "FeeReceiverChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Received", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "totalCharge", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "oracleAggregator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "priceMarkup", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "userOpHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "exchangeRate", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum MultiTokenPaymaster.ExchangeRateSource", + "name": "priceSource", + "type": "uint8" + } + ], + "name": "TokenPaymasterOperation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "charge", + "type": "uint256" + } + ], + "name": "TokenPaymentDue", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_oldSigner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_newSigner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_actor", + "type": "address" + } + ], + "name": "VerifyingSignerChanged", + "type": "event" + }, + { + "inputs": [], + "name": "UNACCOUNTED_COST", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "unstakeDelaySec", + "type": "uint32" + } + ], + "name": "addStake", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "deposit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "entryPoint", + "outputs": [ + { + "internalType": "contract IEntryPoint", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feeReceiver", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getDeposit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "accountGasLimits", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "gasFees", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct PackedUserOperation", + "name": "userOp", + "type": "tuple" + }, + { + "internalType": "enum MultiTokenPaymaster.ExchangeRateSource", + "name": "priceSource", + "type": "uint8" + }, + { + "internalType": "uint48", + "name": "validUntil", + "type": "uint48" + }, + { + "internalType": "uint48", + "name": "validAfter", + "type": "uint48" + }, + { + "internalType": "address", + "name": "feeToken", + "type": "address" + }, + { + "internalType": "address", + "name": "oracleAggregator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "exchangeRate", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "priceMarkup", + "type": "uint32" + } + ], + "name": "getHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + } + ], + "name": "parsePaymasterAndData", + "outputs": [ + { + "internalType": "enum MultiTokenPaymaster.ExchangeRateSource", + "name": "priceSource", + "type": "uint8" + }, + { + "internalType": "uint48", + "name": "validUntil", + "type": "uint48" + }, + { + "internalType": "uint48", + "name": "validAfter", + "type": "uint48" + }, + { + "internalType": "address", + "name": "feeToken", + "type": "address" + }, + { + "internalType": "address", + "name": "oracleAggregator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "exchangeRate", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "priceMarkup", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum IPaymaster.PostOpMode", + "name": "mode", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "context", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "actualGasCost", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actualUserOpFeePerGas", + "type": "uint256" + } + ], + "name": "postOp", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newFeeReceiver", + "type": "address" + } + ], + "name": "setFeeReceiver", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_newThresholdCost", + "type": "uint256" + } + ], + "name": "setUnaccountedEPGasThreshold", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newVerifyingSigner", + "type": "address" + } + ], + "name": "setVerifyingSigner", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unlockStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "accountGasLimits", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "gasFees", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct PackedUserOperation", + "name": "userOp", + "type": "tuple" + }, + { + "internalType": "bytes32", + "name": "userOpHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "maxCost", + "type": "uint256" + } + ], + "name": "validatePaymasterUserOp", + "outputs": [ + { + "internalType": "bytes", + "name": "context", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "validationData", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "verifyingSigner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "dest", + "type": "address" + } + ], + "name": "withdrawAllNative", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdrawERC20", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "withdrawERC20Full", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20[]", + "name": "token", + "type": "address[]" + }, + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "amount", + "type": "uint256[]" + } + ], + "name": "withdrawMultipleERC20", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20[]", + "name": "token", + "type": "address[]" + }, + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "withdrawMultipleERC20Full", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "withdrawAddress", + "type": "address" + } + ], + "name": "withdrawStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "withdrawAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdrawTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] as const; \ No newline at end of file diff --git a/backend/src/abi/VerifyingPaymasterAbiV3.ts b/backend/src/abi/VerifyingPaymasterAbiV3.ts new file mode 100644 index 0000000..5baf8e3 --- /dev/null +++ b/backend/src/abi/VerifyingPaymasterAbiV3.ts @@ -0,0 +1,315 @@ +export const abi = [ + { + inputs: [ + { + internalType: 'contract IEntryPoint', + name: '_entryPoint', + type: 'address', + }, + { + internalType: 'address', + name: '_verifyingSigner', + type: 'address', + }, + ], + stateMutability: 'nonpayable', + type: 'constructor', + }, + { inputs: [], name: 'ECDSAInvalidSignature', type: 'error' }, + { + inputs: [{ internalType: 'uint256', name: 'length', type: 'uint256' }], + name: 'ECDSAInvalidSignatureLength', + type: 'error', + }, + { + inputs: [{ internalType: 'bytes32', name: 's', type: 'bytes32' }], + name: 'ECDSAInvalidSignatureS', + type: 'error', + }, + { + inputs: [{ internalType: 'address', name: 'owner', type: 'address' }], + name: 'OwnableInvalidOwner', + type: 'error', + }, + { + inputs: [{ internalType: 'address', name: 'account', type: 'address' }], + name: 'OwnableUnauthorizedAccount', + type: 'error', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'previousOwner', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'newOwner', + type: 'address', + }, + ], + name: 'OwnershipTransferred', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: 'address', + name: 'newVerifyingSigner', + type: 'address', + }, + ], + name: 'VerifyingSignerUpdated', + type: 'event', + }, + { + inputs: [ + { internalType: 'uint32', name: 'unstakeDelaySec', type: 'uint32' }, + ], + name: 'addStake', + outputs: [], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [], + name: 'deposit', + outputs: [], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [], + name: 'entryPoint', + outputs: [ + { internalType: 'contract IEntryPoint', name: '', type: 'address' }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'getDeposit', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + components: [ + { + internalType: 'address', + name: 'sender', + type: 'address', + }, + { internalType: 'uint256', name: 'nonce', type: 'uint256' }, + { internalType: 'bytes', name: 'initCode', type: 'bytes' }, + { internalType: 'bytes', name: 'callData', type: 'bytes' }, + { + internalType: 'bytes32', + name: 'accountGasLimits', + type: 'bytes32', + }, + { + internalType: 'uint256', + name: 'preVerificationGas', + type: 'uint256', + }, + { + internalType: 'bytes32', + name: 'gasFees', + type: 'bytes32', + }, + { + internalType: 'bytes', + name: 'paymasterAndData', + type: 'bytes', + }, + { internalType: 'bytes', name: 'signature', type: 'bytes' }, + ], + internalType: 'struct PackedUserOperation', + name: 'userOp', + type: 'tuple', + }, + { internalType: 'uint48', name: 'validUntil', type: 'uint48' }, + { internalType: 'uint48', name: 'validAfter', type: 'uint48' }, + ], + name: 'getHash', + outputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'owner', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'bytes', name: 'paymasterAndData', type: 'bytes' }, + ], + name: 'parsePaymasterAndData', + outputs: [ + { internalType: 'uint48', name: 'validUntil', type: 'uint48' }, + { internalType: 'uint48', name: 'validAfter', type: 'uint48' }, + { internalType: 'bytes', name: 'signature', type: 'bytes' }, + ], + stateMutability: 'pure', + type: 'function', + }, + { + inputs: [ + { + internalType: 'enum IPaymaster.PostOpMode', + name: 'mode', + type: 'uint8', + }, + { internalType: 'bytes', name: 'context', type: 'bytes' }, + { internalType: 'uint256', name: 'actualGasCost', type: 'uint256' }, + { + internalType: 'uint256', + name: 'actualUserOpFeePerGas', + type: 'uint256', + }, + ], + name: 'postOp', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'renounceOwnership', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'newOwner', type: 'address' }, + ], + name: 'transferOwnership', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'unlockStake', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '_newVerifyingSigner', + type: 'address', + }, + ], + name: 'updateVerifyingSigner', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + components: [ + { + internalType: 'address', + name: 'sender', + type: 'address', + }, + { internalType: 'uint256', name: 'nonce', type: 'uint256' }, + { internalType: 'bytes', name: 'initCode', type: 'bytes' }, + { internalType: 'bytes', name: 'callData', type: 'bytes' }, + { + internalType: 'bytes32', + name: 'accountGasLimits', + type: 'bytes32', + }, + { + internalType: 'uint256', + name: 'preVerificationGas', + type: 'uint256', + }, + { + internalType: 'bytes32', + name: 'gasFees', + type: 'bytes32', + }, + { + internalType: 'bytes', + name: 'paymasterAndData', + type: 'bytes', + }, + { internalType: 'bytes', name: 'signature', type: 'bytes' }, + ], + internalType: 'struct PackedUserOperation', + name: 'userOp', + type: 'tuple', + }, + { internalType: 'bytes32', name: 'userOpHash', type: 'bytes32' }, + { internalType: 'uint256', name: 'maxCost', type: 'uint256' }, + ], + name: 'validatePaymasterUserOp', + outputs: [ + { internalType: 'bytes', name: 'context', type: 'bytes' }, + { + internalType: 'uint256', + name: 'validationData', + type: 'uint256', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'verifyingSigner', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address payable', + name: 'withdrawAddress', + type: 'address', + }, + ], + name: 'withdrawStake', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address payable', + name: 'withdrawAddress', + type: 'address', + }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + ], + name: 'withdrawTo', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, +]; + +export const byteCode = + '0x60a060405234801561001057600080fd5b506040516114fc3803806114fc83398101604081905261002f916101d2565b81338061005757604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b61006081610096565b5061006a816100b2565b6001600160a01b03908116608052600280546001600160a01b0319169290911691909117905550610235565b600180546001600160a01b03191690556100af8161016d565b50565b6040516301ffc9a760e01b8152631313998b60e31b60048201526001600160a01b038216906301ffc9a790602401602060405180830381865afa1580156100fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610121919061020c565b6100af5760405162461bcd60e51b815260206004820152601e60248201527f49456e747279506f696e7420696e74657266616365206d69736d617463680000604482015260640161004e565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146100af57600080fd5b600080604083850312156101e557600080fd5b82516101f0816101bd565b6020840151909250610201816101bd565b809150509250929050565b60006020828403121561021e57600080fd5b8151801515811461022e57600080fd5b9392505050565b60805161127b610281600039600081816102a60152818161037a01528181610411015281816106be01528181610758015281816107c801528181610855015261094b015261127b6000f3fe6080604052600436106101095760003560e01c806393b9412111610095578063c23a5cea11610064578063c23a5cea146102dd578063c399ec88146102fd578063d0e30db014610312578063e30c39781461031a578063f2fde38b1461033857600080fd5b806393b941211461024457806394d4ad6014610264578063b0d691fe14610294578063bb9fe6bf146102c857600080fd5b80635829c5f5116100dc5780635829c5f5146101ae578063715018a6146101dc57806379ba5097146101f15780637c627b21146102065780638da5cb5b1461022657600080fd5b80630396cb601461010e578063205c28781461012357806323d9ac9b1461014357806352b7512c14610180575b600080fd5b61012161011c366004610e20565b610358565b005b34801561012f57600080fd5b5061012161013e366004610e62565b6103e3565b34801561014f57600080fd5b50600254610163906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561018c57600080fd5b506101a061019b366004610ea7565b610455565b604051610177929190610ef5565b3480156101ba57600080fd5b506101ce6101c9366004610f65565b610479565b604051908152602001610177565b3480156101e857600080fd5b50610121610597565b3480156101fd57600080fd5b506101216105ab565b34801561021257600080fd5b5061012161022136600461100c565b6105f4565b34801561023257600080fd5b506000546001600160a01b0316610163565b34801561025057600080fd5b5061012161025f366004611077565b610610565b34801561027057600080fd5b5061028461027f366004611094565b61066c565b60405161017794939291906110d6565b3480156102a057600080fd5b506101637f000000000000000000000000000000000000000000000000000000000000000081565b3480156102d457600080fd5b506101216106b4565b3480156102e957600080fd5b506101216102f8366004611077565b610731565b34801561030957600080fd5b506101ce6107b0565b610121610840565b34801561032657600080fd5b506001546001600160a01b0316610163565b34801561034457600080fd5b50610121610353366004611077565b6108a2565b610360610913565b604051621cb65b60e51b815263ffffffff821660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630396cb609034906024016000604051808303818588803b1580156103c757600080fd5b505af11580156103db573d6000803e3d6000fd5b505050505050565b6103eb610913565b60405163040b850f60e31b81526001600160a01b038381166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063205c287890604401600060405180830381600087803b1580156103c757600080fd5b60606000610461610940565b61046c8585856109b0565b915091505b935093915050565b6000806104896020860186611077565b905080602086013561049e6040880188611123565b6040516104ac92919061116a565b6040519081900390206104c26060890189611123565b6040516104d092919061116a565b60405190819003902060808901356104eb60e08b018b611123565b6104fa9160349160149161117a565b610503916111a4565b604080516001600160a01b0390971660208801528601949094526060850192909252608084015260a08084019190915260c08084019290925287013560e0830152860135610100820152466101208201523061014082015265ffffffffffff80861661016083015284166101808201526101a001604051602081830303815290604052805190602001209150509392505050565b61059f610913565b6105a96000610b45565b565b60015433906001600160a01b031681146105e85760405163118cdaa760e01b81526001600160a01b03821660048201526024015b60405180910390fd5b6105f181610b45565b50565b6105fc610940565b6106098585858585610b5e565b5050505050565b610618610913565b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527f51d754ac8f7adf515a023f2c423e01ef97817c1af33cb63b36f1fe12fde2d91a9060200160405180910390a150565b600080368161067e856034818961117a565b81019061068b91906111c2565b9094509250858561069e603460406111f5565b6106a992829061117a565b949793965094505050565b6106bc610913565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bb9fe6bf6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561071757600080fd5b505af115801561072b573d6000803e3d6000fd5b50505050565b610739610913565b60405163611d2e7560e11b81526001600160a01b0382811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063c23a5cea90602401600060405180830381600087803b15801561079c57600080fd5b505af1158015610609573d6000803e3d6000fd5b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610817573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061083b9190611216565b905090565b60405163b760faf960e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063b760faf99034906024016000604051808303818588803b15801561079c57600080fd5b6108aa610913565b600180546001600160a01b0383166001600160a01b031990911681179091556108db6000546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6000546001600160a01b031633146105a95760405163118cdaa760e01b81523360048201526024016105df565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146105a95760405162461bcd60e51b815260206004820152601560248201527414d95b99195c881b9bdd08115b9d1c9e541bda5b9d605a1b60448201526064016105df565b60606000808036816109c861027f60e08b018b611123565b9296509094509250905060408114806109e15750604181145b610a55576040805162461bcd60e51b81526020600482015260248101919091527f566572696679696e675061796d61737465723a20696e76616c6964207369676e60448201527f6174757265206c656e67746820696e207061796d6173746572416e644461746160648201526084016105df565b6000610a98610a658b8787610479565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000908152601c91909152603c902090565b9050610ada8184848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610b9692505050565b6002546001600160a01b03908116911614610b1a57610afb60018686610bc2565b6040518060200160405280600081525090965096505050505050610471565b610b2660008686610bc2565b6040805160208101909152600081529b909a5098505050505050505050565b600180546001600160a01b03191690556105f181610bf7565b60405162461bcd60e51b815260206004820152600d60248201526c6d757374206f7665727269646560981b60448201526064016105df565b600080600080610ba68686610c47565b925092509250610bb68282610c94565b50909150505b92915050565b600060d08265ffffffffffff16901b60a08465ffffffffffff16901b85610bea576000610bed565b60015b1717949350505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60008060008351604103610c815760208401516040850151606086015160001a610c7388828585610d51565b955095509550505050610c8d565b50508151600091506002905b9250925092565b6000826003811115610ca857610ca861122f565b03610cb1575050565b6001826003811115610cc557610cc561122f565b03610ce35760405163f645eedf60e01b815260040160405180910390fd5b6002826003811115610cf757610cf761122f565b03610d185760405163fce698f760e01b8152600481018290526024016105df565b6003826003811115610d2c57610d2c61122f565b03610d4d576040516335e2f38360e21b8152600481018290526024016105df565b5050565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115610d8c5750600091506003905082610e16565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015610de0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116610e0c57506000925060019150829050610e16565b9250600091508190505b9450945094915050565b600060208284031215610e3257600080fd5b813563ffffffff81168114610e4657600080fd5b9392505050565b6001600160a01b03811681146105f157600080fd5b60008060408385031215610e7557600080fd5b8235610e8081610e4d565b946020939093013593505050565b60006101208284031215610ea157600080fd5b50919050565b600080600060608486031215610ebc57600080fd5b833567ffffffffffffffff811115610ed357600080fd5b610edf86828701610e8e565b9660208601359650604090950135949350505050565b604081526000835180604084015260005b81811015610f235760208187018101516060868401015201610f06565b506000606082850101526060601f19601f8301168401019150508260208301529392505050565b803565ffffffffffff81168114610f6057600080fd5b919050565b600080600060608486031215610f7a57600080fd5b833567ffffffffffffffff811115610f9157600080fd5b610f9d86828701610e8e565b935050610fac60208501610f4a565b9150610fba60408501610f4a565b90509250925092565b60008083601f840112610fd557600080fd5b50813567ffffffffffffffff811115610fed57600080fd5b60208301915083602082850101111561100557600080fd5b9250929050565b60008060008060006080868803121561102457600080fd5b85356003811061103357600080fd5b9450602086013567ffffffffffffffff81111561104f57600080fd5b61105b88828901610fc3565b9699909850959660408101359660609091013595509350505050565b60006020828403121561108957600080fd5b8135610e4681610e4d565b600080602083850312156110a757600080fd5b823567ffffffffffffffff8111156110be57600080fd5b6110ca85828601610fc3565b90969095509350505050565b65ffffffffffff8516815265ffffffffffff8416602082015260606040820152816060820152818360808301376000818301608090810191909152601f909201601f191601019392505050565b6000808335601e1984360301811261113a57600080fd5b83018035915067ffffffffffffffff82111561115557600080fd5b60200191503681900382131561100557600080fd5b8183823760009101908152919050565b6000808585111561118a57600080fd5b8386111561119757600080fd5b5050820193919092039150565b80356020831015610bbc57600019602084900360031b1b1692915050565b600080604083850312156111d557600080fd5b6111de83610f4a565b91506111ec60208401610f4a565b90509250929050565b80820180821115610bbc57634e487b7160e01b600052601160045260246000fd5b60006020828403121561122857600080fd5b5051919050565b634e487b7160e01b600052602160045260246000fdfea2646970667358221220d60cea746b68db14dc7e0183ce468ee6205af6d23c8f1e604dc54efcf009e45264736f6c634300081d00330000000000000000000000004337084d9e255ff0702461cf8895ce9e3b5ff10800000000000000000000000080a1874e1046b1cc5defdf4d3153838b72ff94ac'; diff --git a/backend/src/constants/ErrorMessage.ts b/backend/src/constants/ErrorMessage.ts index 8ea2a56..081490f 100644 --- a/backend/src/constants/ErrorMessage.ts +++ b/backend/src/constants/ErrorMessage.ts @@ -56,7 +56,8 @@ export default { INVALID_AMOUNT_TO_STAKE: 'Invalid amount to stake', NO_KEY_SET: 'No MTP key set', MULTI_NOT_DEPLOYED: 'Token Paymaster not deployed on the current chainID: ', - COINGECKO_PRICE_NOT_FETCHED: 'Token price not updated, Pls retry.' + COINGECKO_PRICE_NOT_FETCHED: 'Token price not updated, Pls retry.', + MTP_EP_SUPPORT: 'Currently only EPV06 & EPV07 entryPoint addresses are supported', } export function generateErrorMessage(template: string, values: { [key: string]: string | number }): string { diff --git a/backend/src/constants/MultitokenPaymaster.ts b/backend/src/constants/MultitokenPaymaster.ts index 862d1e8..598f418 100644 --- a/backend/src/constants/MultitokenPaymaster.ts +++ b/backend/src/constants/MultitokenPaymaster.ts @@ -189,7 +189,8 @@ export const TokenDecimalsAndSymbol: Record> = '0x4e352cF164E64ADCBad318C3a1e222E9EBa4Ce42': { decimals: 18, symbol: 'MCB' }, '0x51fC0f6660482Ea73330E414eFd7808811a57Fa2': { decimals: 18, symbol: 'PREMIA' }, '0xD74f5255D557944cf7Dd0E45FF521520002D5748': { decimals: 18, symbol: 'USDs' }, - '0x9ed7E4B1BFF939ad473dA5E7a218C771D1569456': { decimals: 6, symbol: 'REUNI' } + '0x9ed7E4B1BFF939ad473dA5E7a218C771D1569456': { decimals: 6, symbol: 'REUNI' }, + '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE': { decimals: 18, symbol: 'ETH' } }, 43114: { '0x62edc0692BD897D2295872a9FFCac5425011c661': { decimals: 18, symbol: 'GMX' }, diff --git a/backend/src/constants/Pimlico.ts b/backend/src/constants/Token.ts similarity index 100% rename from backend/src/constants/Pimlico.ts rename to backend/src/constants/Token.ts diff --git a/backend/src/models/api-key.ts b/backend/src/models/api-key.ts index 0a778d7..aa36062 100644 --- a/backend/src/models/api-key.ts +++ b/backend/src/models/api-key.ts @@ -9,7 +9,9 @@ export class APIKey extends Model { public erc20PaymastersV2?: string | null; public verifyingPaymasters?: string | null; public verifyingPaymastersV2?: string | null; + public verifyingPaymastersV3?: string | null; public multiTokenPaymasters?: string | null; + public multiTokenPaymastersV2?: string | null; public multiTokenOracles?: string | null; public sponsorName?: string | null; public logoUrl?: string | null; @@ -66,6 +68,11 @@ export function initializeAPIKeyModel(sequelize: Sequelize, schema: string) { allowNull: true, field: 'VERIFYING_PAYMASTERS_V2' }, + verifyingPaymastersV3: { + type: DataTypes.TEXT, + allowNull: true, + field: 'VERIFYING_PAYMASTERS_V3' + }, bundlerApiKey: { type: DataTypes.TEXT, allowNull: true, @@ -77,6 +84,11 @@ export function initializeAPIKeyModel(sequelize: Sequelize, schema: string) { allowNull: true, field: 'MULTI_TOKEN_PAYMASTERS' }, + multiTokenPaymastersV2: { + type: DataTypes.TEXT, + allowNull: true, + field: 'MULTI_TOKEN_PAYMASTERS_V2' + }, multiTokenOracles: { type: DataTypes.TEXT, allowNull: true, diff --git a/backend/src/models/multiTokenPaymaster.ts b/backend/src/models/multiTokenPaymaster.ts index bd4320d..a31bc72 100644 --- a/backend/src/models/multiTokenPaymaster.ts +++ b/backend/src/models/multiTokenPaymaster.ts @@ -7,6 +7,7 @@ export class MultiTokenPaymaster extends Model { public paymasterAddress!: string; public chainId!: number; public decimals!: string; + public epVersion!: string; public readonly createdAt!: Date; public readonly updatedAt!: Date; } @@ -50,6 +51,11 @@ const initializeMTPModel = (sequelize: Sequelize, schema: string) => { allowNull: false, field: 'DECIMALS' }, + epVersion: { + type: DataTypes.STRING, + allowNull: false, + field: 'EP_VERSION' + }, createdAt: { type: DataTypes.DATE, allowNull: false, diff --git a/backend/src/models/whitelist.ts b/backend/src/models/whitelist.ts index b26b097..c3954ee 100644 --- a/backend/src/models/whitelist.ts +++ b/backend/src/models/whitelist.ts @@ -5,6 +5,7 @@ export class ArkaWhitelist extends Model { public apiKey!: string; public addresses!: string[]; public policyId?: number; + public epVersion?: string | null = null; public readonly createdAt!: Date; public readonly updatedAt!: Date; } @@ -34,6 +35,11 @@ const initializeArkaWhitelistModel = (sequelize: Sequelize, schema: string) => { allowNull: true, field: 'POLICY_ID' }, + epVersion: { + type: DataTypes.STRING, + allowNull: true, + field: 'EP_VERSION', + }, createdAt: { type: DataTypes.DATE, allowNull: false, diff --git a/backend/src/paymaster/index.test.ts b/backend/src/paymaster/index.test.ts index e77770e..a29740c 100644 --- a/backend/src/paymaster/index.test.ts +++ b/backend/src/paymaster/index.test.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { ethers, providers, Wallet } from "ethers"; import { Paymaster } from "./index.js"; -import { PAYMASTER_ADDRESS } from "../constants/Pimlico.js"; +import { PAYMASTER_ADDRESS } from "../constants/Token.js"; import MultiTokenPaymasterAbi from "../abi/MultiTokenPaymasterAbi.js"; describe("Validate the Arka Paymaster on Sepolia", () => { diff --git a/backend/src/paymaster/index.ts b/backend/src/paymaster/index.ts index 3fba6fa..f1fa9ac 100644 --- a/backend/src/paymaster/index.ts +++ b/backend/src/paymaster/index.ts @@ -4,9 +4,9 @@ import { arrayify, BytesLike, defaultAbiCoder, hexConcat, hexZeroPad } from 'eth import { FastifyBaseLogger } from 'fastify'; import EtherspotAbiV06 from '../abi/EtherspotAbi.js'; import EtherspotAbiV07 from "../abi/EtherspotVerifyingSignerAbi.js"; -import { PimlicoPaymaster } from './pimlico.js'; +import { TokenPaymaster } from './token.js'; import ErrorMessage from '../constants/ErrorMessage.js'; -import { PAYMASTER_ADDRESS } from '../constants/Pimlico.js'; +import { PAYMASTER_ADDRESS } from '../constants/Token.js'; import { getGasFee } from '../utils/common.js'; import MultiTokenPaymasterAbi from '../abi/MultiTokenPaymasterAbi.js'; import OrochiOracleAbi from '../abi/OrochiOracleAbi.js'; @@ -21,6 +21,9 @@ import { CoingeckoService } from '../services/coingecko.js'; import { Sequelize } from 'sequelize'; import { abi as verifyingPaymasterAbi, byteCode as verifyingPaymasterByteCode } from '../abi/VerifyingPaymasterAbi.js'; import { abi as verifyingPaymasterV2Abi, byteCode as verifyingPaymasterV2ByteCode } from '../abi/VerifyingPaymasterAbiV2.js'; +import { abi as verifyingPaymasterV3Abi, byteCode as verifyingPaymasterV3ByteCode } from '../abi/VerifyingPaymasterAbiV3.js'; +import { EPVersions } from '../types/sponsorship-policy-dto.js'; +import MultiTokenPaymasterAbiV2 from '../abi/MultiTokenPaymasterAbiV2.js'; const ttl = parseInt(process.env.CACHE_TTL || "600000"); const nativePriceCacheTtl = parseInt(process.env.NATIVE_PRICE_CACHE_TTL || "60000"); @@ -54,13 +57,17 @@ export class Paymaster { EP7_TOKEN_VGL: string; EP7_TOKEN_PGL: string; EP7_PVGL: BigNumber; + EP8_PVGL: BigNumber; + MTP_PVGL: string; + MTP_PPGL: string; priceAndMetadata: Map = new Map(); nativeCurrencyPrice: Map = new Map(); coingeckoPrice: Map = new Map(); coingeckoService: CoingeckoService = new CoingeckoService(); sequelize: Sequelize; - constructor(feeMarkUp: string, multiTokenMarkUp: string, ep7TokenVGL: string, ep7TokenPGL: string, sequelize: Sequelize, mtpVglMarkup: string, ep7Pvgl: string) { + constructor(feeMarkUp: string, multiTokenMarkUp: string, ep7TokenVGL: string, ep7TokenPGL: string, sequelize: Sequelize, + mtpVglMarkup: string, ep7Pvgl: string, mtpPvgl: string, mtpPpgl: string, ep8Pvgl: string) { this.feeMarkUp = ethers.utils.parseUnits(feeMarkUp, 'gwei'); if (isNaN(Number(multiTokenMarkUp))) this.multiTokenMarkUp = 1150000 // 15% more of the actual cost. Can be anything between 1e6 to 2e6 else this.multiTokenMarkUp = Number(multiTokenMarkUp); @@ -69,6 +76,9 @@ export class Paymaster { this.sequelize = sequelize; this.MTP_VGL_MARKUP = mtpVglMarkup; this.EP7_PVGL = BigNumber.from(ep7Pvgl); + this.EP8_PVGL = BigNumber.from(ep8Pvgl); + this.MTP_PVGL = mtpPvgl; + this.MTP_PPGL = mtpPpgl; } packUint(high128: BigNumberish, low128: BigNumberish): string { @@ -115,7 +125,7 @@ export class Paymaster { const paymasterPostOpGasLimit = BigNumber.from("40000").toHexString(); if (estimate) { userOp.paymaster = paymasterAddress; - userOp.paymasterVerificationGasLimit = this.EP7_PVGL; + userOp.paymasterVerificationGasLimit = this.EP7_PVGL.toHexString(); userOp.paymasterPostOpGasLimit = paymasterPostOpGasLimit; const accountGasLimits = this.packUint(userOp.verificationGasLimit, userOp.callGasLimit) const gasFees = this.packUint(userOp.maxPriorityFeePerGas, userOp.maxFeePerGas); @@ -178,6 +188,80 @@ export class Paymaster { } } + async signV08(userOp: any, validUntil: string, validAfter: string, entryPoint: string, paymasterAddress: string, + bundlerRpc: string, signer: Wallet, estimate: boolean, log?: FastifyBaseLogger) { + try { + const provider = new providers.JsonRpcProvider(bundlerRpc); + const paymasterContract = new ethers.Contract(paymasterAddress, verifyingPaymasterV3Abi, provider); + if (!userOp.signature) userOp.signature = '0x'; + if (userOp.factory && userOp.factoryData) userOp.initCode = hexConcat([userOp.factory, userOp.factoryData ?? '']) + if (!userOp.initCode) userOp.initCode = "0x"; + const paymasterPostOpGasLimit = BigNumber.from("40000").toHexString(); + if (estimate) { + userOp.paymaster = paymasterAddress; + userOp.paymasterVerificationGasLimit = this.EP8_PVGL.toHexString(); + userOp.paymasterPostOpGasLimit = paymasterPostOpGasLimit; + const accountGasLimits = this.packUint(userOp.verificationGasLimit, userOp.callGasLimit) + const gasFees = this.packUint(userOp.maxPriorityFeePerGas, userOp.maxFeePerGas); + const packedUserOp = { + sender: userOp.sender, + nonce: userOp.nonce, + initCode: userOp.initCode, + callData: userOp.callData, + accountGasLimits: accountGasLimits, + preVerificationGas: userOp.preVerificationGas, + gasFees: gasFees, + paymasterAndData: this.packPaymasterData(paymasterAddress, this.EP8_PVGL, paymasterPostOpGasLimit), + signature: userOp.signature + } + userOp.paymasterData = await this.getPaymasterData(packedUserOp, validUntil, validAfter, paymasterContract, signer); + const response = await provider.send('eth_estimateUserOperationGas', [userOp, entryPoint]); + userOp.verificationGasLimit = response.verificationGasLimit; + userOp.callGasLimit = response.callGasLimit; + userOp.preVerificationGas = response.preVerificationGas; + } + const accountGasLimits = this.packUint(userOp.verificationGasLimit, userOp.callGasLimit) + const gasFees = this.packUint(userOp.maxPriorityFeePerGas, userOp.maxFeePerGas); + const packedUserOp = { + sender: userOp.sender, + nonce: userOp.nonce, + initCode: userOp.initCode, + callData: userOp.callData, + accountGasLimits: accountGasLimits, + preVerificationGas: userOp.preVerificationGas, + gasFees: gasFees, + paymasterAndData: this.packPaymasterData(paymasterAddress, this.EP8_PVGL, paymasterPostOpGasLimit), + signature: userOp.signature + } + + const paymasterData = await this.getPaymasterData(packedUserOp, validUntil, validAfter, paymasterContract, signer); + let returnValue; + if (estimate) { + returnValue = { + paymaster: paymasterAddress, + paymasterData: paymasterData, + preVerificationGas: BigNumber.from(packedUserOp.preVerificationGas).toHexString(), + verificationGasLimit: BigNumber.from(userOp.verificationGasLimit).toHexString(), + callGasLimit: BigNumber.from(userOp.callGasLimit).toHexString(), + paymasterVerificationGasLimit: this.EP8_PVGL.toHexString(), + paymasterPostOpGasLimit + } + } else { + returnValue = { + paymaster: paymasterAddress, + paymasterData: paymasterData, + } + } + + return returnValue; + } catch (err: any) { + if (err.message.includes("Quota exceeded")) + throw new Error('Failed to process request to bundler since request Quota exceeded for the current apiKey') + if (log) log.error(err, 'signV08'); + throw new Error(`Failed to process request to bundler. Please contact support team RawErrorMsg: ${err.message}`) + } + } + async getPaymasterAndData(userOp: any, validUntil: string, validAfter: string, paymasterContract: Contract, signer: Wallet) { // actual signing... const hash = await paymasterContract.getHash( @@ -237,6 +321,38 @@ export class Paymaster { } } + async getPaymasterAndDataForMultiTokenPaymasterV07(userOp: any, validUntil: string, validAfter: string, feeToken: string, + ethPrice: string, paymasterContract: Contract, signer: Wallet) { + try { + const priceMarkup = this.multiTokenMarkUp; + const hash = await paymasterContract.getHash( + userOp, + 0, + validUntil, + validAfter, + feeToken, + ethers.constants.AddressZero, + ethPrice, + priceMarkup + ); + + const sig = await signer.signMessage(arrayify(hash)); + + const paymasterData = hexConcat([ + '0x00', + defaultAbiCoder.encode( + ['uint48', 'uint48', 'address', 'address', 'uint256', 'uint32'], + [validUntil, validAfter, feeToken, ethers.constants.AddressZero, ethPrice, priceMarkup] + ), + sig, + ]); + + return paymasterData; + } catch (err: any) { + throw new Error('Failed ' + err.message) + } + } + async getPaymasterAndDataForMultiTokenPaymaster(userOp: any, validUntil: string, validAfter: string, feeToken: string, ethPrice: string, paymasterContract: Contract, signer: Wallet, chainId: number) { const priceMarkup = this.multiTokenMarkUp; @@ -717,7 +833,7 @@ export class Paymaster { userOp.paymasterAndData = paymasterAndData const response = await provider.send('eth_estimateUserOperationGas', [userOp, entryPoint]); if (BigNumber.from(userOp.verificationGasLimit).lt("45000")) userOp.verificationGasLimit = BigNumber.from("45000").toHexString(); // This is to counter the unaccounted cost(45000) - userOp.verificationGasLimit = BigNumber.from(response.verificationGasLimit).add("30000").toHexString(); // This is added just in case the token is proxy + userOp.verificationGasLimit = BigNumber.from(response.verificationGasLimit).add(this.MTP_VGL_MARKUP).toHexString(); // This is added just in case the token is proxy userOp.preVerificationGas = response.preVerificationGas; userOp.callGasLimit = response.callGasLimit; paymasterAndData = await this.getPaymasterAndDataForMultiTokenPaymaster(userOp, validUntil, validAfter, feeToken, ethPrice, paymasterContract, signer, chainId); @@ -738,10 +854,106 @@ export class Paymaster { } } - async pimlico(userOp: any, bundlerRpc: string, entryPoint: string, PaymasterAddress: string, log?: FastifyBaseLogger) { + async signMultiTokenPaymasterV07(userOp: any, validUntil: string, validAfter: string, entryPoint: string, paymasterAddress: string, + feeToken: string, oracleAggregator: string, bundlerRpc: string, signer: Wallet, oracleName: string, nativeOracleAddress: string, + chainId: number, log?: FastifyBaseLogger) { + try { + const provider = new providers.JsonRpcProvider(bundlerRpc); + const paymasterContract = new ethers.Contract(paymasterAddress, MultiTokenPaymasterAbiV2, provider); + let ethPrice; + const isCoingeckoAvailable = this.coingeckoPrice.get(`${chainId}-${feeToken}`); + + if (!oracleAggregator) { + if (!isCoingeckoAvailable) throw new Error('Unable to fetch token price. Please try again later.') + const { latestAnswer, decimals } = await this.getLatestAnswerAndDecimals(provider, nativeOracleAddress, chainId); + const data = await this.getPriceFromCoingecko(chainId, feeToken, latestAnswer, decimals, log); + + ethPrice = data.ethPrice; + } else if (oracleName === "orochi") { + const data = await this.getPriceFromOrochi(oracleAggregator, provider, feeToken, chainId); + ethPrice = data.ethPrice; + } else if (oracleName === "chainlink") { + const { latestAnswer, decimals } = await this.getLatestAnswerAndDecimals(provider, nativeOracleAddress, chainId); + + const data = await this.getPriceFromChainlink( + oracleAggregator, + provider, + feeToken, + latestAnswer, + decimals, + chainId + ); + + ethPrice = data.ethPrice; + } else { + const ecContract = new ethers.Contract(oracleAggregator, EtherspotChainlinkOracleAbi, provider); + const ETHprice = await ecContract.cachedPrice(); + ethPrice = ETHprice + } + if (userOp.factory && userOp.factoryData) userOp.initCode = hexConcat([userOp.factory, userOp.factoryData ?? '']) + if (!userOp.signature) userOp.signature = '0x'; + userOp.paymaster = paymasterAddress; + userOp.paymasterVerificationGasLimit = BigNumber.from(this.MTP_PVGL).toHexString(); // Paymaster specific gas limit + userOp.paymasterPostOpGasLimit = BigNumber.from(this.MTP_PPGL).toHexString(); // Paymaster specific gas limit for token transfer + let accountGasLimits = this.packUint(userOp.verificationGasLimit, userOp.callGasLimit) + const gasFees = this.packUint(userOp.maxPriorityFeePerGas, userOp.maxFeePerGas); + let packedUserOp = { + sender: userOp.sender, + nonce: userOp.nonce, + initCode: userOp.initCode ?? "0x", + callData: userOp.callData, + accountGasLimits: accountGasLimits, + preVerificationGas: userOp.preVerificationGas, + gasFees: gasFees, + paymasterAndData: this.packPaymasterData(paymasterAddress, userOp.paymasterVerificationGasLimit, userOp.paymasterPostOpGasLimit, "0x"), + signature: userOp.signature + } + userOp.paymaster = paymasterAddress; + let paymasterData = await this.getPaymasterAndDataForMultiTokenPaymasterV07(packedUserOp, validUntil, validAfter, feeToken, ethPrice, paymasterContract, signer); + userOp.paymasterData = paymasterData + userOp.paymasterAndData = this.packPaymasterData(paymasterAddress, userOp.paymasterVerificationGasLimit, userOp.paymasterPostOpGasLimit, paymasterData); + const response = await provider.send('eth_estimateUserOperationGas', [userOp, entryPoint]); + if (BigNumber.from(userOp.verificationGasLimit).lt("45000")) userOp.verificationGasLimit = BigNumber.from("45000").toHexString(); // This is to counter the unaccounted cost(45000) + userOp.verificationGasLimit = response.verificationGasLimit; + userOp.preVerificationGas = response.preVerificationGas; + userOp.callGasLimit = response.callGasLimit; + accountGasLimits = this.packUint(userOp.verificationGasLimit, userOp.callGasLimit); + packedUserOp = { + sender: userOp.sender, + nonce: userOp.nonce, + initCode: userOp.initCode ?? "0x", + callData: userOp.callData, + accountGasLimits: accountGasLimits, + preVerificationGas: userOp.preVerificationGas, + gasFees: gasFees, + paymasterAndData: this.packPaymasterData(paymasterAddress, userOp.paymasterVerificationGasLimit, userOp.paymasterPostOpGasLimit, paymasterData), + signature: userOp.signature + } + paymasterData = await this.getPaymasterAndDataForMultiTokenPaymasterV07(packedUserOp, validUntil, validAfter, feeToken, ethPrice, paymasterContract, signer); + userOp.paymasterData = paymasterData + + const returnValue = { + paymaster: paymasterAddress, + paymasterData: paymasterData, + preVerificationGas: BigNumber.from(packedUserOp.preVerificationGas).toHexString(), + verificationGasLimit: BigNumber.from(userOp.verificationGasLimit).toHexString(), + callGasLimit: BigNumber.from(userOp.callGasLimit).toHexString(), + paymasterVerificationGasLimit: userOp.paymasterVerificationGasLimit, + paymasterPostOpGasLimit: userOp.paymasterPostOpGasLimit, + } + return returnValue; + } catch (err: any) { + if (err.message.includes("Quota exceeded")) + throw new Error('Failed to process request to bundler since request Quota exceeded for the current apiKey') + if (log) log.error(err, 'signMultiTokenPaymasterV07'); + throw new Error('Failed to process request to bundler. Please contact support team RawErrorMsg:' + err.message) + } + } + + async erc20Paymaster(userOp: any, bundlerRpc: string, entryPoint: string, PaymasterAddress: string, log?: FastifyBaseLogger) { try { const provider = new providers.JsonRpcProvider(bundlerRpc); - const erc20Paymaster = new PimlicoPaymaster(PaymasterAddress, provider) + const erc20Paymaster = new TokenPaymaster(PaymasterAddress, provider) if (!userOp.signature) userOp.signature = '0x'; // The minimum ABI to get the ERC20 Token balance @@ -785,7 +997,7 @@ export class Paymaster { if (err.message.includes("Quota exceeded")) throw new Error('Failed to process request to bundler since request Quota exceeded for the current apiKey') if (err.message.includes('The required token amount')) throw new Error(err.message); - if (log) log.error(err, 'pimlico'); + if (log) log.error(err, 'erc20Paymaster'); throw new Error('Failed to process request to bundler. Please contact support team RawErrorMsg: ' + err.message) } } @@ -860,13 +1072,13 @@ export class Paymaster { } } - async pimlicoAddress(gasToken: string, chainId: number, log?: FastifyBaseLogger) { + async erc20PaymasterAddress(gasToken: string, chainId: number, log?: FastifyBaseLogger) { try { return { message: PAYMASTER_ADDRESS[chainId][gasToken] ?? 'Requested Token Paymaster is not available/deployed', } } catch (err: any) { - if (log) log.error(err, 'pimlicoAddress'); + if (log) log.error(err, 'ERC20PaymasterAddress'); throw new Error(err.message) } } @@ -1047,7 +1259,7 @@ export class Paymaster { privateKey: string, bundlerRpcUrl: string, epAddr: string, - isEp06: boolean, + epVersion: EPVersions, chainId: number, log?: FastifyBaseLogger ) { @@ -1056,10 +1268,12 @@ export class Paymaster { const signer = new Wallet(privateKey, provider); let contract; - if (isEp06) { + if (epVersion === EPVersions.EPV_06) { contract = new ethers.ContractFactory(verifyingPaymasterAbi, verifyingPaymasterByteCode, signer); - } else { + } else if (epVersion === EPVersions.EPV_07) { contract = new ethers.ContractFactory(verifyingPaymasterV2Abi, verifyingPaymasterV2ByteCode, signer); + } else { + contract = new ethers.ContractFactory(verifyingPaymasterV3Abi, verifyingPaymasterV3ByteCode, signer); } const etherscanFeeData = await getGasFee(chainId, bundlerRpcUrl, log); @@ -1192,7 +1406,7 @@ export class Paymaster { const tokenData = this.coingeckoPrice.get(cacheKey)?.data; if (!tokenData) { log?.error('Price fetch error on tokenAddress: ' + tokenAddress, 'CoingeckoError') - throw new Error(tokenAddress + ' ' +ErrorMessage.COINGECKO_PRICE_NOT_FETCHED); + throw new Error(`${tokenAddress} ${ErrorMessage.COINGECKO_PRICE_NOT_FETCHED}`); } } } diff --git a/backend/src/paymaster/pimlico.test.ts b/backend/src/paymaster/token.test.ts similarity index 98% rename from backend/src/paymaster/pimlico.test.ts rename to backend/src/paymaster/token.test.ts index 0e372ea..625c94a 100644 --- a/backend/src/paymaster/pimlico.test.ts +++ b/backend/src/paymaster/token.test.ts @@ -1,13 +1,13 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { providers, ethers } from "ethers"; -import { PimlicoPaymaster, getERC20Paymaster } from "./pimlico.js"; +import { TokenPaymaster, getERC20Paymaster } from "./token.js"; import { NATIVE_ASSET, ORACLE_ADDRESS, TOKEN_ADDRESS, -} from "../../src/constants/Pimlico.js"; +} from "../constants/Token.js"; -describe("PimlicoPaymaster on Mumbai", () => { +describe("TokenPaymaster on Mumbai", () => { const paymasterAddress = "0x32aCDFeA07a614E52403d2c1feB747aa8079A353"; // Mumbai Etherspot Paymaster Address const entryPointAddress = "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789"; // EntryPoint v0.6 as default const bundlerUrl = "https://mumbai-bundler.etherspot.io"; @@ -39,12 +39,12 @@ describe("PimlicoPaymaster on Mumbai", () => { }; const provider = new providers.JsonRpcProvider(bundlerUrl); - const pimlicoPaymaster = new PimlicoPaymaster(paymasterAddress, provider); + const tokenPaymaster = new TokenPaymaster(paymasterAddress, provider); test.skip("SMOKE: validate the calculateTokenAmount function with valid details", async () => { try { const calculateTokenAmountResponse = - await pimlicoPaymaster.calculateTokenAmount(userOp); + await tokenPaymaster.calculateTokenAmount(userOp); try { expect(calculateTokenAmountResponse).toHaveProperty("_hex"); @@ -63,7 +63,7 @@ describe("PimlicoPaymaster on Mumbai", () => { test.skip("SMOKE: validate the generatePaymasterAndData function with valid details", async () => { try { const generatePaymasterAndDataResponse = - await pimlicoPaymaster.generatePaymasterAndData(userOp); + await tokenPaymaster.generatePaymasterAndData(userOp); try { expect(generatePaymasterAndDataResponse.length.toString()).toMatch( "106" diff --git a/backend/src/paymaster/pimlico.ts b/backend/src/paymaster/token.ts similarity index 96% rename from backend/src/paymaster/pimlico.ts rename to backend/src/paymaster/token.ts index e1ce5f7..47b0237 100644 --- a/backend/src/paymaster/pimlico.ts +++ b/backend/src/paymaster/token.ts @@ -1,8 +1,8 @@ import { Contract, BigNumber, providers, utils, Signer, ethers } from "ethers"; import { UserOperationStruct } from "@account-abstraction/contracts" import { NotPromise } from "@account-abstraction/utils" -import abi from "../abi/PimlicoAbi.js"; -import { NATIVE_ASSET, ORACLE_ADDRESS, TOKEN_ADDRESS, bytecode } from "../constants/Pimlico.js"; +import abi from "../abi/ERC20PaymasterAbi.js"; +import { NATIVE_ASSET, ORACLE_ADDRESS, TOKEN_ADDRESS, bytecode } from "../constants/Token.js"; export interface ERC20PaymasterBuildOptions { entrypoint?: string @@ -14,7 +14,7 @@ export interface ERC20PaymasterBuildOptions { deployer?: Signer } -export class PimlicoPaymaster { +export class TokenPaymaster { private contract: Contract; tokenAddress: Promise; paymasterAddress: string; @@ -52,7 +52,6 @@ export class PimlicoPaymaster { /** * Don't know why but the below calculation is for tokens with 6 decimals such as USDC, USDT - * Pimlico default paymasters uses only USDC * After long testing the below code is neglected for tokens with 18 decimals */ if (ethers.utils.parseUnits('1', 6).eq(tokenDecimals)) { @@ -190,7 +189,7 @@ export async function getERC20Paymaster( erc20: string, entryPoint: string, options?: Omit, "deployer"> -): Promise { +): Promise { let parsedOptions: Required, "deployer">> const chainId = (await provider.getNetwork()).chainId if (options === undefined) { @@ -199,7 +198,7 @@ export async function getERC20Paymaster( nativeAssetOracle: ORACLE_ADDRESS[chainId][NATIVE_ASSET[chainId]], tokenAddress: TOKEN_ADDRESS[chainId][erc20], tokenOracle: ORACLE_ADDRESS[chainId][erc20], - owner: "0x4337000c2828F5260d8921fD25829F606b9E8680" // pimlico address + owner: "0x4337000c2828F5260d8921fD25829F606b9E8680" } } else { parsedOptions = await validatePaymasterOptions(provider, erc20, options) @@ -208,5 +207,5 @@ export async function getERC20Paymaster( if ((await provider.getCode(address)).length <= 2) { throw new Error(`ERC20Paymaster not deployed at ${address}`) } - return new PimlicoPaymaster(address, provider) + return new TokenPaymaster(address, provider) } diff --git a/backend/src/plugins/config.ts b/backend/src/plugins/config.ts index c125234..7b280ea 100644 --- a/backend/src/plugins/config.ts +++ b/backend/src/plugins/config.ts @@ -25,19 +25,23 @@ const ConfigSchema = Type.Strict( DATABASE_SCHEMA_NAME: Type.String() || undefined, HMAC_SECRET: Type.String({ minLength: 1 }), UNSAFE_MODE: Type.Boolean() || undefined, - EP7_TOKEN_VGL: Type.String() || '90000', - EP7_TOKEN_PGL: Type.String() || '150000', - EPV_06: Type.Array(Type.String()) || ['0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789'], - EPV_07: Type.Array(Type.String()) || ['0x0000000071727De22E5E9d8BAf0edAc6f37da032'], + EP7_TOKEN_VGL: Type.String() || undefined, + EP7_TOKEN_PGL: Type.String() || undefined, + EPV_06: Type.Array(Type.String()), + EPV_07: Type.Array(Type.String()), + EPV_08: Type.Array(Type.String()), DELETE_KEY_RECOVER_WINDOW: Type.Number(), KMS_KEY_ID: Type.String() || undefined, USE_KMS: Type.Boolean() || false, DEFAULT_BUNDLER_API_KEY: Type.String(), MULTI_TOKEN_PAYMASTERS: Type.String(), MULTI_TOKEN_ORACLES: Type.String(), - MTP_VGL_MARKUP: Type.String() || '30000', + MTP_VGL_MARKUP: Type.String() || undefined, USE_SKANDHA_FOR_GAS_DATA: Type.Boolean() || true, EP7_PVGL: Type.String(), + EP8_PVGL: Type.String(), + MTP_PVGL: Type.String() || undefined, + MTP_PPGL: Type.String() || undefined, }) ); @@ -71,6 +75,7 @@ const configPlugin: FastifyPluginAsync = async (server) => { EP7_TOKEN_PGL: process.env.EP7_TOKEN_PGL, EPV_06: process.env.EPV_06?.split(','), EPV_07: process.env.EPV_07?.split(','), + EPV_08: process.env.EPV_08?.split(','), DELETE_KEY_RECOVER_WINDOW: process.env.DELETE_KEY_RECOVER_WINDOW, KMS_KEY_ID: process.env.KMS_KEY_ID, USE_KMS: process.env.USE_KMS, @@ -80,6 +85,9 @@ const configPlugin: FastifyPluginAsync = async (server) => { MTP_VGL_MARKUP: process.env.MTP_VGL_MARKUP, USE_SKANDHA_FOR_GAS_DATA: process.env.USE_SKANDHA_FOR_GAS_DATA, EP7_PVGL: process.env.EP7_PVGL ?? '30000', + EP8_PVGL: process.env.EP8_PVGL ?? '30000', + MTP_PVGL: process.env.MTP_PVGL ?? '50000', + MTP_PPGL: process.env.MTP_PPGL ?? '70000', } const valid = validate(envVar); @@ -109,6 +117,7 @@ const configPlugin: FastifyPluginAsync = async (server) => { EP7_TOKEN_PGL: process.env.EP7_TOKEN_PGL ?? '150000', EPV_06: process.env.EPV_06?.split(',') ?? ['0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789'], EPV_07: process.env.EPV_07?.split(',') ?? ['0x0000000071727De22E5E9d8BAf0edAc6f37da032'], + EPV_08: process.env.EPV_08?.split(',') ?? ['0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108'], DELETE_KEY_RECOVER_WINDOW: parseInt(process.env.DELETE_KEY_RECOVER_WINDOW || '7'), KMS_KEY_ID: process.env.KMS_KEY_ID ?? '', USE_KMS: process.env.USE_KMS === 'true', @@ -117,7 +126,10 @@ const configPlugin: FastifyPluginAsync = async (server) => { MULTI_TOKEN_ORACLES: process.env.MULTI_TOKEN_ORACLES ?? '', MTP_VGL_MARKUP: process.env.MTP_VGL_MARKUP ?? '30000', USE_SKANDHA_FOR_GAS_DATA: process.env.USE_SKANDHA_FOR_GAS_DATA === 'false' ? false : true, - EP7_PVGL: process.env.EP7_PVGL ?? '30000' + EP7_PVGL: process.env.EP7_PVGL ?? '30000', + EP8_PVGL: process.env.EP8_PVGL ?? '30000', + MTP_PVGL: process.env.MTP_PVGL ?? '50000', + MTP_PPGL: process.env.MTP_PPGL ?? '70000', } server.log.info(config, "config:"); diff --git a/backend/src/repository/api-key-repository.ts b/backend/src/repository/api-key-repository.ts index 804ff7b..ed60b74 100644 --- a/backend/src/repository/api-key-repository.ts +++ b/backend/src/repository/api-key-repository.ts @@ -1,6 +1,7 @@ import { Sequelize } from 'sequelize'; import { APIKey } from '../models/api-key.js'; import { ApiKeyDto } from '../types/apikey-dto.js'; +import { EPVersions } from '../types/sponsorship-policy-dto.js'; export class APIKeyRepository { private sequelize: Sequelize; @@ -60,10 +61,15 @@ export class APIKeyRepository { return result ? result.get() as APIKey : null; } - async updateVpAddresses(apiKey: string, vpAddresses: string, isEp06 = true) { - if (isEp06) { - return await this.sequelize.models.APIKey.update({verifyingPaymasters: vpAddresses}, {where: {apiKey}}); + async updateVpAddresses(apiKey: string, vpAddresses: string, epVersion: EPVersions = EPVersions.EPV_06) { + if (epVersion === EPVersions.EPV_06) { + return await this.sequelize.models.APIKey.update({ verifyingPaymasters: vpAddresses }, { where: { apiKey } }); + } else if (epVersion === EPVersions.EPV_07) { + return await this.sequelize.models.APIKey.update({ verifyingPaymastersV2: vpAddresses }, { where: { apiKey } }); + } else if (epVersion === EPVersions.EPV_08) { + return await this.sequelize.models.APIKey.update({ verifyingPaymastersV3: vpAddresses }, { where: { apiKey } }); + } else { + throw new Error(`Unsupported EP version: ${epVersion}`); } - return await this.sequelize.models.APIKey.update({verifyingPaymastersV2: vpAddresses}, {where: {apiKey}}); } } \ No newline at end of file diff --git a/backend/src/repository/multi-token-paymaster.ts b/backend/src/repository/multi-token-paymaster.ts index e6957a4..4018bea 100644 --- a/backend/src/repository/multi-token-paymaster.ts +++ b/backend/src/repository/multi-token-paymaster.ts @@ -1,5 +1,6 @@ import { Sequelize } from 'sequelize'; import { MultiTokenPaymaster } from '../models/multiTokenPaymaster.js'; +import { EPVersions } from '../types/sponsorship-policy-dto.js'; export class MultiTokenPaymasterRepository { private sequelize: Sequelize; @@ -13,10 +14,10 @@ export class MultiTokenPaymasterRepository { return result.map(id => id.get() as MultiTokenPaymaster); } - async findOneByChainIdAndTokenAddress(chainId: number, tokenAddress: string): Promise { + async findOneByChainIdEPVersionAndTokenAddress(chainId: number, tokenAddress: string, epVersion: EPVersions): Promise { const result = await this.sequelize.models.MultiTokenPaymaster.findOne({ where: { - chainId: chainId, tokenAddress: tokenAddress + chainId: chainId, tokenAddress: tokenAddress, epVersion: epVersion } }) as MultiTokenPaymaster; diff --git a/backend/src/repository/whitelist-repository.ts b/backend/src/repository/whitelist-repository.ts index a6b6e0f..d0a283c 100644 --- a/backend/src/repository/whitelist-repository.ts +++ b/backend/src/repository/whitelist-repository.ts @@ -1,6 +1,7 @@ import { Sequelize } from 'sequelize'; import { WhitelistDto } from '../types/whitelist-dto.js'; import { ArkaWhitelist } from '../models/whitelist.js'; +import { EPVersions } from '../types/sponsorship-policy-dto.js'; export class WhitelistRepository { private sequelize: Sequelize; @@ -14,7 +15,8 @@ export class WhitelistRepository { const result = await this.sequelize.models.ArkaWhitelist.create({ apiKey: apiKey.apiKey, addresses: apiKey.addresses, - policyId: apiKey.policyId ?? null + policyId: apiKey.policyId ?? null, + epVersion: apiKey.epVersion ?? null }) as ArkaWhitelist; @@ -50,6 +52,19 @@ export class WhitelistRepository { return result ? result.get() as ArkaWhitelist : null; } + async findOneByApiKeyEPVersionAndPolicyId(apiKey: string, epVersion: EPVersions, policyId?: number): Promise { + let result; + if (!epVersion) { + return null; + } + if (policyId) { + result = await this.sequelize.models.ArkaWhitelist.findOne({ where: { apiKey: apiKey, epVersion: epVersion, policyId: policyId } }); + } else { + result = await this.sequelize.models.ArkaWhitelist.findOne({ where: { apiKey: apiKey, epVersion: epVersion, policyId: null } }); + } + return result ? result.get() as ArkaWhitelist : null; + } + async updateOneById(record: ArkaWhitelist): Promise { const result = await this.sequelize.models.ArkaWhitelist.update({ apiKey: record.apiKey, diff --git a/backend/src/routes/admin-routes.ts b/backend/src/routes/admin-routes.ts index cc86b1e..2b39c35 100644 --- a/backend/src/routes/admin-routes.ts +++ b/backend/src/routes/admin-routes.ts @@ -18,7 +18,8 @@ import { getNetworkConfig } from "../utils/common.js"; import { Paymaster } from "../paymaster/index.js"; const adminRoutes: FastifyPluginAsync = async (server) => { - const paymaster = new Paymaster(server.config.FEE_MARKUP, server.config.MULTI_TOKEN_MARKUP, server.config.EP7_TOKEN_VGL, server.config.EP7_TOKEN_PGL, server.sequelize, server.config.MTP_VGL_MARKUP, server.config.EP7_PVGL); + const paymaster = new Paymaster(server.config.FEE_MARKUP, server.config.MULTI_TOKEN_MARKUP, server.config.EP7_TOKEN_VGL, server.config.EP7_TOKEN_PGL, server.sequelize, + server.config.MTP_VGL_MARKUP, server.config.EP7_PVGL, server.config.MTP_PVGL, server.config.MTP_PPGL, server.config.EP8_PVGL); const prefixSecretId = 'arka_'; @@ -32,7 +33,8 @@ const adminRoutes: FastifyPluginAsync = async (server) => { const SUPPORTED_ENTRYPOINTS = { EPV_06: server.config.EPV_06, - EPV_07: server.config.EPV_07 + EPV_07: server.config.EPV_07, + EPV_08: server.config.EPV_08 } @@ -384,21 +386,25 @@ const adminRoutes: FastifyPluginAsync = async (server) => { return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_DATA }); } - if (!epVersion || (epVersion !== EPVersions.EPV_06 && epVersion !== EPVersions.EPV_07)) { + if (!epVersion || (epVersion !== EPVersions.EPV_06 && epVersion !== EPVersions.EPV_07 && epVersion !== EPVersions.EPV_08)) { return reply.code(ReturnCode.FAILURE).send({error: ErrorMessage.INVALID_EP_VERSION}); } - const isEp06 = epVersion === EPVersions.EPV_06; - const apiKeyEntity: APIKey | null = await server.apiKeyRepository.findOneByApiKey(apiKey); if (!apiKeyEntity) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }); let verifyingPaymasters; + let supportedEPs; - if(isEp06) { + if(epVersion === EPVersions.EPV_06) { verifyingPaymasters = apiKeyEntity.verifyingPaymasters ? JSON.parse(apiKeyEntity.verifyingPaymasters) : {}; - } else { + supportedEPs = SUPPORTED_ENTRYPOINTS.EPV_06; + } else if(epVersion === EPVersions.EPV_07) { verifyingPaymasters = apiKeyEntity.verifyingPaymastersV2 ? JSON.parse(apiKeyEntity.verifyingPaymastersV2) : {}; + supportedEPs = SUPPORTED_ENTRYPOINTS.EPV_07; + } else { + verifyingPaymasters = apiKeyEntity.verifyingPaymastersV3 ? JSON.parse(apiKeyEntity.verifyingPaymastersV3) : {}; + supportedEPs = SUPPORTED_ENTRYPOINTS.EPV_08; } if (verifyingPaymasters[chainId]) { return reply.code(ReturnCode.FAILURE).send( @@ -440,7 +446,7 @@ const adminRoutes: FastifyPluginAsync = async (server) => { const networkConfig = getNetworkConfig( chainId, supportedNetworks ?? '', - isEp06 ? SUPPORTED_ENTRYPOINTS.EPV_06 : SUPPORTED_ENTRYPOINTS.EPV_07 + supportedEPs ); if (!networkConfig) { @@ -455,12 +461,12 @@ const adminRoutes: FastifyPluginAsync = async (server) => { privateKey, bundlerUrl, networkConfig.entryPoint, - isEp06, + epVersion, chainId, server.log ); verifyingPaymasters[chainId] = address; - await server.apiKeyRepository.updateVpAddresses(apiKey, JSON.stringify(verifyingPaymasters), isEp06); + await server.apiKeyRepository.updateVpAddresses(apiKey, JSON.stringify(verifyingPaymasters), epVersion); return reply.code(ReturnCode.SUCCESS).send({verifyingPaymaster: address, txHash: hash}); } catch (error: any) { @@ -488,21 +494,24 @@ const adminRoutes: FastifyPluginAsync = async (server) => { return reply.code(ReturnCode.FAILURE).send({error: ErrorMessage.INVALID_AMOUNT_TO_STAKE}); } - if (!epVersion || (epVersion !== EPVersions.EPV_06 && epVersion !== EPVersions.EPV_07)) { + if (!epVersion || (epVersion !== EPVersions.EPV_06 && epVersion !== EPVersions.EPV_07 && epVersion !== EPVersions.EPV_08)) { return reply.code(ReturnCode.FAILURE).send({error: ErrorMessage.INVALID_EP_VERSION}); } - const isEp06 = epVersion === EPVersions.EPV_06; - const apiKeyEntity: APIKey | null = await server.apiKeyRepository.findOneByApiKey(apiKey); if (!apiKeyEntity) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }); - let verifyingPaymasters; + let verifyingPaymasters, supportedEPs; - if(isEp06) { + if(epVersion === EPVersions.EPV_06) { verifyingPaymasters = apiKeyEntity.verifyingPaymasters ? JSON.parse(apiKeyEntity.verifyingPaymasters) : {}; - } else { + supportedEPs = SUPPORTED_ENTRYPOINTS.EPV_06; + } else if (epVersion === EPVersions.EPV_07) { verifyingPaymasters = apiKeyEntity.verifyingPaymastersV2 ? JSON.parse(apiKeyEntity.verifyingPaymastersV2) : {}; + supportedEPs = SUPPORTED_ENTRYPOINTS.EPV_07; + } else { + verifyingPaymasters = apiKeyEntity.verifyingPaymastersV3 ? JSON.parse(apiKeyEntity.verifyingPaymastersV3) : {}; + supportedEPs = SUPPORTED_ENTRYPOINTS.EPV_08; } if (!verifyingPaymasters[chainId]) { @@ -544,7 +553,7 @@ const adminRoutes: FastifyPluginAsync = async (server) => { const networkConfig = getNetworkConfig( chainId, supportedNetworks ?? '', - isEp06 ? SUPPORTED_ENTRYPOINTS.EPV_06 : SUPPORTED_ENTRYPOINTS.EPV_07 + supportedEPs ); if (!networkConfig) { return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); diff --git a/backend/src/routes/deposit-route.ts b/backend/src/routes/deposit-route.ts index a5ca99f..6fd8a96 100644 --- a/backend/src/routes/deposit-route.ts +++ b/backend/src/routes/deposit-route.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { Type } from "@sinclair/typebox"; -import { FastifyPluginAsync } from "fastify"; +import { FastifyPluginAsync, FastifyReply, FastifyRequest } from "fastify"; import { GetSecretValueCommand, SecretsManagerClient } from "@aws-sdk/client-secrets-manager"; import { Paymaster } from "../paymaster/index.js"; import SupportedNetworks from "../../config.json" assert { type: "json" }; @@ -9,13 +9,16 @@ import ReturnCode from "../constants/ReturnCode.js"; import { decode } from "../utils/crypto.js"; import { printRequest, getNetworkConfig } from "../utils/common.js"; import { APIKey } from "../models/api-key.js"; +import { EPVersions } from "../types/sponsorship-policy-dto.js"; const depositRoutes: FastifyPluginAsync = async (server) => { - const paymaster = new Paymaster(server.config.FEE_MARKUP, server.config.MULTI_TOKEN_MARKUP, server.config.EP7_TOKEN_VGL, server.config.EP7_TOKEN_PGL, server.sequelize, server.config.MTP_VGL_MARKUP, server.config.EP7_PVGL); + const paymaster = new Paymaster(server.config.FEE_MARKUP, server.config.MULTI_TOKEN_MARKUP, server.config.EP7_TOKEN_VGL, server.config.EP7_TOKEN_PGL, server.sequelize, + server.config.MTP_VGL_MARKUP, server.config.EP7_PVGL, server.config.MTP_PVGL, server.config.MTP_PPGL, server.config.EP8_PVGL); const SUPPORTED_ENTRYPOINTS = { EPV_06: server.config.EPV_06, - EPV_07: server.config.EPV_07 + EPV_07: server.config.EPV_07, + EPV_08: server.config.EPV_08 } const prefixSecretId = 'arka_'; @@ -41,145 +44,109 @@ const depositRoutes: FastifyPluginAsync = async (server) => { } } + async function deposit(request: FastifyRequest, reply: FastifyReply, epVersion: EPVersions) { + try { + const body: any = request.body; + if (!body) { + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.EMPTY_BODY }) + } + const query: any = request.query; + const amount = body.params?.[0]; + const useVp = query['useVp'] ?? false; + const chainId = query['chainId'] ?? body.params?.[1]; + const api_key = query['apiKey'] ?? body.params?.[2]; + + if (!api_key || typeof(api_key) !== "string") + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) + let privateKey = ''; + let bundlerApiKey = api_key; + const apiKeyEntity: APIKey | null = await server.apiKeyRepository.findOneByApiKey(api_key); + if (!apiKeyEntity) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) + if (!unsafeMode) { + const AWSresponse = await client.send( + new GetSecretValueCommand({ + SecretId: prefixSecretId + api_key, + }) + ); + const secrets = JSON.parse(AWSresponse.SecretString ?? '{}'); + if (!secrets['PRIVATE_KEY']) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) + privateKey = secrets['PRIVATE_KEY']; + } else { + privateKey = decode(apiKeyEntity.privateKey, server.config.HMAC_SECRET); + } + const supportedNetworks = apiKeyEntity.supportedNetworks; + if (apiKeyEntity.bundlerApiKey) { + bundlerApiKey = apiKeyEntity.bundlerApiKey; + } + if ( + isNaN(amount) || + !chainId || + isNaN(chainId) + ) { + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_DATA }); + } + if (server.config.SUPPORTED_NETWORKS == '' && !SupportedNetworks) { + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); + } + let networkConfig; + let vpAddr; + if (EPVersions.EPV_06 == epVersion) { + networkConfig = getNetworkConfig(chainId, supportedNetworks ?? '', SUPPORTED_ENTRYPOINTS.EPV_06); + vpAddr = apiKeyEntity.verifyingPaymasters ? + JSON.parse(apiKeyEntity.verifyingPaymasters)[chainId] : + undefined; + } else if (EPVersions.EPV_07 == epVersion) { + networkConfig = getNetworkConfig(chainId, supportedNetworks ?? '', SUPPORTED_ENTRYPOINTS.EPV_07); + vpAddr = apiKeyEntity.verifyingPaymastersV2 ? + JSON.parse(apiKeyEntity.verifyingPaymastersV2)[chainId] : + undefined; + } else if (EPVersions.EPV_08 == epVersion) { + networkConfig = getNetworkConfig(chainId, supportedNetworks ?? '', SUPPORTED_ENTRYPOINTS.EPV_08); + vpAddr = apiKeyEntity.verifyingPaymastersV3 ? + JSON.parse(apiKeyEntity.verifyingPaymastersV3)[chainId] : + undefined; + } + if (!networkConfig) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); + let bundlerUrl = networkConfig.bundler; + if (networkConfig.bundler.includes('etherspot.io')) bundlerUrl = `${networkConfig.bundler}?api-key=${bundlerApiKey}`; + + if(!useVp) { + return await paymaster.deposit(amount, networkConfig.contracts.etherspotPaymasterAddress, bundlerUrl, privateKey, chainId, true, server.log); + } + if(!vpAddr) { + return reply.code(ReturnCode.FAILURE).send({error: ErrorMessage.VP_NOT_DEPLOYED}) + } + + return await paymaster.deposit(amount, vpAddr, bundlerUrl, privateKey, chainId, false, server.log); + } catch (err: any) { + request.log.error(err); + if (err.name == "ResourceNotFoundException") + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }); + return reply.code(ReturnCode.FAILURE).send({ error: err.message ?? ErrorMessage.FAILED_TO_PROCESS }) + } + } + server.post("/deposit", ResponseSchema, async function (request, reply) { - try { - printRequest("/deposit", request, server.log); - const body: any = request.body; - if (!body) { - return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.EMPTY_BODY }) - } - const query: any = request.query; - const amount = body.params?.[0]; - const useVp = query['useVp'] ?? false; - const chainId = query['chainId'] ?? body.params?.[1]; - const api_key = query['apiKey'] ?? body.params?.[2]; - - if (!api_key || typeof(api_key) !== "string") - return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) - let privateKey = ''; - let bundlerApiKey = api_key; - const apiKeyEntity: APIKey | null = await server.apiKeyRepository.findOneByApiKey(api_key); - if (!apiKeyEntity) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) - if (!unsafeMode) { - const AWSresponse = await client.send( - new GetSecretValueCommand({ - SecretId: prefixSecretId + api_key, - }) - ); - const secrets = JSON.parse(AWSresponse.SecretString ?? '{}'); - if (!secrets['PRIVATE_KEY']) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) - privateKey = secrets['PRIVATE_KEY']; - } else { - privateKey = decode(apiKeyEntity.privateKey, server.config.HMAC_SECRET); - } - const supportedNetworks = apiKeyEntity.supportedNetworks; - if (apiKeyEntity.bundlerApiKey) { - bundlerApiKey = apiKeyEntity.bundlerApiKey; - } - if ( - isNaN(amount) || - !chainId || - isNaN(chainId) - ) { - return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_DATA }); - } - if (server.config.SUPPORTED_NETWORKS == '' && !SupportedNetworks) { - return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); - } - const networkConfig = getNetworkConfig(chainId, supportedNetworks ?? '', SUPPORTED_ENTRYPOINTS.EPV_06); - if (!networkConfig) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); - let bundlerUrl = networkConfig.bundler; - if (networkConfig.bundler.includes('etherspot.io')) bundlerUrl = `${networkConfig.bundler}?api-key=${bundlerApiKey}`; - - if(!useVp) { - return await paymaster.deposit(amount, networkConfig.contracts.etherspotPaymasterAddress, bundlerUrl, privateKey, chainId, true, server.log); - } - const vpAddr = apiKeyEntity.verifyingPaymasters ? - JSON.parse(apiKeyEntity.verifyingPaymasters)[chainId] : - undefined; - if(!vpAddr) { - return reply.code(ReturnCode.FAILURE).send({error: ErrorMessage.VP_NOT_DEPLOYED}) - } - - return await paymaster.deposit(amount, vpAddr, bundlerUrl, privateKey, chainId, false, server.log); - } catch (err: any) { - request.log.error(err); - if (err.name == "ResourceNotFoundException") - return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }); - return reply.code(ReturnCode.FAILURE).send({ error: err.message ?? ErrorMessage.FAILED_TO_PROCESS }) - } + printRequest("/deposit", request, server.log); + return await deposit(request, reply, EPVersions.EPV_06); } ) server.post("/deposit/v2", ResponseSchema, async function (request, reply) { - try { - printRequest("/deposit/v2", request, server.log); - const body: any = request.body; - const query: any = request.query; - if (!body) { - return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.EMPTY_BODY }) - } - const amount = body.params?.[0]; - const chainId = query['chainId'] ?? body.params?.[1]; - const api_key = query['apiKey'] ?? body.params?.[2]; - const useVp = query['useVp'] ?? false; - if (!api_key || typeof(api_key) !== "string") - return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) - let privateKey = ''; - let bundlerApiKey = api_key; - const apiKeyEntity: APIKey | null = await server.apiKeyRepository.findOneByApiKey(api_key); - if (!apiKeyEntity) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) - if (!unsafeMode) { - const AWSresponse = await client.send( - new GetSecretValueCommand({ - SecretId: prefixSecretId + api_key, - }) - ); - const secrets = JSON.parse(AWSresponse.SecretString ?? '{}'); - if (!secrets['PRIVATE_KEY']) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) - privateKey = secrets['PRIVATE_KEY']; - } else { - privateKey = decode(apiKeyEntity.privateKey, server.config.HMAC_SECRET); - } - const supportedNetworks = apiKeyEntity.supportedNetworks; - if (apiKeyEntity.bundlerApiKey) { - bundlerApiKey = apiKeyEntity.bundlerApiKey; - } - if ( - isNaN(amount) || - !chainId || - isNaN(chainId) - ) { - return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_DATA }); - } - if (server.config.SUPPORTED_NETWORKS == '' && !SupportedNetworks) { - return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); - } - const networkConfig = getNetworkConfig(chainId, supportedNetworks ?? '', SUPPORTED_ENTRYPOINTS.EPV_07); - if (!networkConfig) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); - let bundlerUrl = networkConfig.bundler; - if (networkConfig.bundler.includes('etherspot.io')) bundlerUrl = `${networkConfig.bundler}?api-key=${bundlerApiKey}`; + printRequest("/deposit/v2", request, server.log); + return await deposit(request, reply, EPVersions.EPV_07); + } + ) - if(!useVp) { - return await paymaster.deposit(amount, networkConfig.contracts.etherspotPaymasterAddress, bundlerUrl, privateKey, chainId, false, server.log); - } - const vpAddr = apiKeyEntity.verifyingPaymastersV2 ? - JSON.parse(apiKeyEntity.verifyingPaymastersV2)[chainId] : - undefined; - if(!vpAddr) { - return reply.code(ReturnCode.FAILURE).send({error: ErrorMessage.VP_NOT_DEPLOYED}) - } - return await paymaster.deposit(amount, vpAddr, bundlerUrl, privateKey, chainId, false, server.log); - } catch (err: any) { - request.log.error(err); - if (err.name == "ResourceNotFoundException") - return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }); - return reply.code(ReturnCode.FAILURE).send({ error: err.message ?? ErrorMessage.FAILED_TO_PROCESS }) - } + server.post("/deposit/v3", + ResponseSchema, + async function (request, reply) { + printRequest("/deposit/v3", request, server.log); + return await deposit(request, reply, EPVersions.EPV_08); } ) }; diff --git a/backend/src/routes/metadata-routes.ts b/backend/src/routes/metadata-routes.ts index b446d46..8678dcd 100644 --- a/backend/src/routes/metadata-routes.ts +++ b/backend/src/routes/metadata-routes.ts @@ -7,10 +7,12 @@ import { getNetworkConfig, printRequest } from "../utils/common.js"; import ReturnCode from "../constants/ReturnCode.js"; import ErrorMessage from "../constants/ErrorMessage.js"; import { decode } from "../utils/crypto.js"; -import { PAYMASTER_ADDRESS } from "../constants/Pimlico.js"; +import { PAYMASTER_ADDRESS } from "../constants/Token.js"; import { APIKey } from "../models/api-key.js"; import * as EtherspotAbi from "../abi/EtherspotAbi.js"; import {abi as verifyingPaymasterAbi} from "../abi/VerifyingPaymasterAbi.js"; +import {abi as verifyingPaymasterV2Abi} from "../abi/VerifyingPaymasterAbiV2.js"; +import {abi as verifyingPaymastersV3Abi} from "../abi/VerifyingPaymasterAbiV3.js"; const metadataRoutes: FastifyPluginAsync = async (server) => { @@ -18,7 +20,8 @@ const metadataRoutes: FastifyPluginAsync = async (server) => { const SUPPORTED_ENTRYPOINTS = { EPV_06: server.config.EPV_06, - EPV_07: server.config.EPV_07 + EPV_07: server.config.EPV_07, + EPV_08: server.config.EPV_08 } let client: SecretsManagerClient; @@ -119,6 +122,7 @@ const metadataRoutes: FastifyPluginAsync = async (server) => { verifyingPaymaster: { address: verifyingPaymaster, deposit: verifyingPaymasterDeposit }, verifyingPaymasters: apiKeyEntity.verifyingPaymasters ? JSON.parse(apiKeyEntity.verifyingPaymasters) : undefined, verifyingPaymastersV2: apiKeyEntity.verifyingPaymastersV2 ? JSON.parse(apiKeyEntity.verifyingPaymastersV2) : undefined, + verifyingPaymastersV3: apiKeyEntity.verifyingPaymastersV3 ? JSON.parse(apiKeyEntity.verifyingPaymastersV3) : undefined, }) } catch (err: any) { request.log.error(err); @@ -195,7 +199,7 @@ const metadataRoutes: FastifyPluginAsync = async (server) => { const verifyingPaymaster = apiKeyEntity.verifyingPaymastersV2 ? JSON.parse(apiKeyEntity.verifyingPaymastersV2)[chainId] : undefined; let verifyingPaymasterDeposit; if (verifyingPaymaster) { - const vpContract = new Contract(verifyingPaymaster, verifyingPaymasterAbi ,provider); + const vpContract = new Contract(verifyingPaymaster, verifyingPaymasterV2Abi ,provider); verifyingPaymasterDeposit = await vpContract.getDeposit(); } const chainsSupported: { chainId: number, entryPoint: string }[] = []; @@ -217,6 +221,103 @@ const metadataRoutes: FastifyPluginAsync = async (server) => { verifyingPaymaster: { address: verifyingPaymaster, deposit: verifyingPaymasterDeposit }, verifyingPaymasters: apiKeyEntity.verifyingPaymasters ? JSON.parse(apiKeyEntity.verifyingPaymasters) : undefined, verifyingPaymastersV2: apiKeyEntity.verifyingPaymastersV2 ? JSON.parse(apiKeyEntity.verifyingPaymastersV2) : undefined, + verifyingPaymastersV3: apiKeyEntity.verifyingPaymastersV3 ? JSON.parse(apiKeyEntity.verifyingPaymastersV3) : undefined, + }) + } catch (err: any) { + request.log.error(err); + if (err.name == "ResourceNotFoundException") + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }); + return reply.code(ReturnCode.FAILURE).send({ error: err.message ?? ErrorMessage.FAILED_TO_PROCESS }); + } + }) + + server.get('/metadata/v3', async function (request, reply) { + try { + printRequest('/metadata/v3', request, server.log); + const query: any = request.query; + const chainId = query['chainId'] ?? 137; + const api_key = query['apiKey']; + if (!api_key || typeof(api_key) !== "string") + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) + if (!chainId) + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_DATA }) + let customPaymasters = []; + let multiTokenPaymasters = []; + let privateKey = ''; + let sponsorName = '', sponsorImage = ''; + let bundlerApiKey = api_key; + const apiKeyEntity: APIKey | null = await server.apiKeyRepository.findOneByApiKey(api_key); + if (!apiKeyEntity) { + server.log.info("Invalid Api Key provided") + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) + } + if (!unsafeMode) { + const AWSresponse = await client.send( + new GetSecretValueCommand({ + SecretId: prefixSecretId + api_key, + }) + ); + const secrets = JSON.parse(AWSresponse.SecretString ?? '{}'); + if (!secrets['PRIVATE_KEY']) { + server.log.info("Invalid Api Key provided") + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) + } + privateKey = secrets['PRIVATE_KEY']; + } else { + privateKey = decode(apiKeyEntity.privateKey, server.config.HMAC_SECRET); + } + if (apiKeyEntity.erc20Paymasters) { + const buffer = Buffer.from(apiKeyEntity.erc20Paymasters, 'base64'); + customPaymasters = JSON.parse(buffer.toString()); + } + if (apiKeyEntity.multiTokenPaymasters) { + const buffer = Buffer.from(apiKeyEntity.multiTokenPaymasters, 'base64'); + multiTokenPaymasters = JSON.parse(buffer.toString()); + } + if (apiKeyEntity.bundlerApiKey) { + bundlerApiKey = apiKeyEntity.bundlerApiKey; + } + sponsorName = apiKeyEntity.sponsorName ? apiKeyEntity.sponsorName : ""; + sponsorImage = apiKeyEntity.logoUrl ? apiKeyEntity.logoUrl : ""; + const supportedNetworks = apiKeyEntity.supportedNetworks; + if (server.config.SUPPORTED_NETWORKS == '' && !SupportedNetworks) { + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); + } + const networkConfig = getNetworkConfig(chainId, supportedNetworks ?? '', SUPPORTED_ENTRYPOINTS.EPV_08); + if (!networkConfig) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); + let bundlerUrl = networkConfig.bundler; + if (bundlerUrl.includes('etherspot.io')) bundlerUrl = `${networkConfig.bundler}?api-key=${bundlerApiKey}`; + const provider = new providers.JsonRpcProvider(bundlerUrl); + const signer = new Wallet(privateKey, provider) + const sponsorWalletBalance = await signer.getBalance(); + const sponsorAddress = await signer.getAddress(); + + const verifyingPaymaster = apiKeyEntity.verifyingPaymastersV3 ? JSON.parse(apiKeyEntity.verifyingPaymastersV3)[chainId] : undefined; + let verifyingPaymasterDeposit; + if (verifyingPaymaster) { + const vpContract = new Contract(verifyingPaymaster, verifyingPaymastersV3Abi ,provider); + verifyingPaymasterDeposit = await vpContract.getDeposit(); + } + const chainsSupported: { chainId: number, entryPoint: string }[] = []; + SupportedNetworks.map(element => { + chainsSupported.push({ chainId: element.chainId, entryPoint: element.entryPoint }); + }) + const tokenPaymasterAddresses = { + ...PAYMASTER_ADDRESS, + ...customPaymasters, + } + return reply.code(ReturnCode.SUCCESS).send({ + sponsorAddress: sponsorAddress, + sponsorWalletBalance: sponsorWalletBalance, + sponsorBalance: verifyingPaymasterDeposit ?? 0, + chainsSupported: chainsSupported, + tokenPaymasters: tokenPaymasterAddresses, + multiTokenPaymasters, + sponsorDetails: { name: sponsorName, icon: sponsorImage }, + verifyingPaymaster: { address: verifyingPaymaster, deposit: verifyingPaymasterDeposit }, + verifyingPaymasters: apiKeyEntity.verifyingPaymasters ? JSON.parse(apiKeyEntity.verifyingPaymasters) : undefined, + verifyingPaymastersV2: apiKeyEntity.verifyingPaymastersV2 ? JSON.parse(apiKeyEntity.verifyingPaymastersV2) : undefined, + verifyingPaymastersV3: apiKeyEntity.verifyingPaymastersV3 ? JSON.parse(apiKeyEntity.verifyingPaymastersV3) : undefined, }) } catch (err: any) { request.log.error(err); diff --git a/backend/src/routes/paymaster-routes.ts b/backend/src/routes/paymaster-routes.ts index 9166b09..7c295af 100644 --- a/backend/src/routes/paymaster-routes.ts +++ b/backend/src/routes/paymaster-routes.ts @@ -4,7 +4,7 @@ import { BigNumber, Wallet, ethers, providers } from "ethers"; import { gql, request as GLRequest } from "graphql-request"; import { GetSecretValueCommand, SecretsManagerClient } from "@aws-sdk/client-secrets-manager"; import SupportedNetworks from "../../config.json" assert { type: "json" }; -import { PAYMASTER_ADDRESS } from "../constants/Pimlico.js"; +import { PAYMASTER_ADDRESS } from "../constants/Token.js"; import ErrorMessage, { generateErrorMessage } from "../constants/ErrorMessage.js"; import ReturnCode from "../constants/ReturnCode.js"; import { decode } from "../utils/crypto.js"; @@ -16,11 +16,12 @@ import { PaymasterRoutesOpts } from "../types/arka-config-dto.js"; const paymasterRoutes: FastifyPluginAsync = async (server, options: PaymasterRoutesOpts) => { - const {paymaster} = options; + const { paymaster } = options; const SUPPORTED_ENTRYPOINTS = { EPV_06: server.config.EPV_06, - EPV_07: server.config.EPV_07 + EPV_07: server.config.EPV_07, + EPV_08: server.config.EPV_08 } const prefixSecretId = 'arka_'; @@ -88,11 +89,11 @@ const paymasterRoutes: FastifyPluginAsync = async (server, } if (!api_key || typeof (api_key) !== "string") return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) - if (!SUPPORTED_ENTRYPOINTS.EPV_06?.includes(entryPoint) && !SUPPORTED_ENTRYPOINTS.EPV_07?.includes(entryPoint)) - return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_ENTRYPOINT }) - + if (SUPPORTED_ENTRYPOINTS.EPV_06?.includes(entryPoint)) epVersion = EPVersions.EPV_06; - else epVersion = EPVersions.EPV_07; + else if (SUPPORTED_ENTRYPOINTS.EPV_07?.includes(entryPoint)) epVersion = EPVersions.EPV_07; + else if (SUPPORTED_ENTRYPOINTS.EPV_08?.includes(entryPoint)) epVersion = EPVersions.EPV_08; + else return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_ENTRYPOINT }) let customPaymasters = []; let customPaymastersV2 = []; @@ -102,6 +103,7 @@ const paymasterRoutes: FastifyPluginAsync = async (server, let sponsorName = '', sponsorImage = ''; let contractWhitelistMode = false; let bundlerApiKey = api_key; + let multiTokenPaymastersV2 = []; const apiKeyEntity = await server.apiKeyRepository.findOneByApiKey(api_key); @@ -141,6 +143,11 @@ const paymasterRoutes: FastifyPluginAsync = async (server, multiTokenPaymasters = JSON.parse(buffer.toString()); } + if (apiKeyEntity.multiTokenPaymastersV2) { + const buffer = Buffer.from(apiKeyEntity.multiTokenPaymastersV2, 'base64'); + multiTokenPaymastersV2 = JSON.parse(buffer.toString()); + } + if (apiKeyEntity.multiTokenOracles) { const buffer = Buffer.from(apiKeyEntity.multiTokenOracles, 'base64'); multiTokenOracles = JSON.parse(buffer.toString()); @@ -196,13 +203,7 @@ const paymasterRoutes: FastifyPluginAsync = async (server, else { if (gasToken && ethers.utils.isAddress(gasToken)) gasToken = ethers.utils.getAddress(gasToken) - if (mode.toLowerCase() == 'multitoken' && - !(multiTokenPaymasters[chainId] && multiTokenPaymasters[chainId][gasToken]) && - !(multiTokenOracles[chainId] && multiTokenOracles[chainId][gasToken]) && - !paymaster.coingeckoPrice.get(`${chainId}-${gasToken}`) - ) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK_TOKEN }) - - if(useVp && mode.toLowerCase() === 'sponsor') { + if (useVp && mode.toLowerCase() === 'sponsor') { mode = 'vps'; } @@ -254,15 +255,22 @@ const paymasterRoutes: FastifyPluginAsync = async (server, const contractWhitelistResult = await checkContractWhitelist(userOp.callData, chainId.chainId, signer.address); if (!contractWhitelistResult) throw new Error('Contract Method not whitelisted'); } + const isWhitelisted = await checkWhitelist(api_key, epVersion, userOp.sender, sponsorshipPolicy.id); + if (!isWhitelisted) { + throw new Error('This sender address has not been whitelisted yet'); + } if (epVersion === EPVersions.EPV_06) result = await paymaster.signV06(userOp, str, str1, entryPoint, networkConfig.contracts.etherspotPaymasterAddress, bundlerUrl, signer, estimate, server.log); - else { - const globalWhitelistRecord = await server.whitelistRepository.findOneByApiKeyAndPolicyId(api_key); - if (!globalWhitelistRecord?.addresses.includes(userOp.sender)) { - const existingWhitelistRecord = await server.whitelistRepository.findOneByApiKeyAndPolicyId(api_key, sponsorshipPolicy.id); - if (!existingWhitelistRecord?.addresses.includes(userOp.sender)) throw new Error('This sender address has not been whitelisted yet'); + else if (epVersion === EPVersions.EPV_07) { + if (!networkConfig.contracts.etherspotPaymasterAddress) { + throw new Error('Please use useVP flag to use your deployed verifying paymaster as global paymaster is not defined'); } result = await paymaster.signV07(userOp, str, str1, entryPoint, networkConfig.contracts.etherspotPaymasterAddress, bundlerUrl, signer, estimate, server.log); + } else { + if (!networkConfig.contracts.etherspotPaymasterAddress) { + throw new Error('Please use useVP flag to use your deployed verifying paymaster as global paymaster is not defined'); + } + result = await paymaster.signV08(userOp, str, str1, entryPoint, networkConfig.contracts.etherspotPaymasterAddress, bundlerUrl, signer, estimate, server.log); } break; } @@ -275,7 +283,7 @@ const paymasterRoutes: FastifyPluginAsync = async (server, let paymasterAddress: string; if (customPaymasters[chainId] && customPaymasters[chainId][gasToken]) paymasterAddress = customPaymasters[chainId][gasToken]; else paymasterAddress = PAYMASTER_ADDRESS[chainId][gasToken] - result = await paymaster.pimlico(userOp, bundlerUrl, entryPoint, paymasterAddress, server.log); + result = await paymaster.erc20Paymaster(userOp, bundlerUrl, entryPoint, paymasterAddress, server.log); } else if (epVersion === EPVersions.EPV_07) { if ( !(customPaymastersV2[chainId] && customPaymastersV2[chainId][gasToken]) @@ -288,9 +296,17 @@ const paymasterRoutes: FastifyPluginAsync = async (server, break; } case 'multitoken': { - if (epVersion !== EPVersions.EPV_06) - throw new Error('Currently only EPV06 entryPoint address is supported') - if (!(multiTokenPaymasters[chainId] && multiTokenPaymasters[chainId][gasToken])) + if (epVersion !== EPVersions.EPV_06 && epVersion !== EPVersions.EPV_07) + throw new Error(ErrorMessage.MTP_EP_SUPPORT) + let paymasterAddress: string; + if (epVersion === EPVersions.EPV_06) { + paymasterAddress = multiTokenPaymasters[chainId]?.[gasToken]; + } else { + paymasterAddress = multiTokenPaymastersV2[chainId]?.[gasToken]; + } + if (!paymasterAddress) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK_TOKEN }) + if (!(multiTokenOracles[chainId] && multiTokenOracles[chainId][gasToken]) && + !paymaster.coingeckoPrice.get(`${chainId}-${gasToken}`)) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK_TOKEN }) const date = new Date(); const provider = new providers.JsonRpcProvider(bundlerUrl); @@ -314,7 +330,11 @@ const paymasterRoutes: FastifyPluginAsync = async (server, throw new Error("Oracle is not Defined/Invalid"); if (networkConfig.MultiTokenPaymasterOracleUsed == "chainlink" && !NativeOracles[chainId]) throw new Error("Native Oracle address not set for this chainId") - result = await paymaster.signMultiTokenPaymaster(userOp, str, str1, entryPoint, multiTokenPaymasters[chainId][gasToken], gasToken, multiTokenOracles[chainId] ? multiTokenOracles[chainId][gasToken] : '', bundlerUrl, signer, networkConfig.MultiTokenPaymasterOracleUsed, NativeOracles[chainId], chainId, server.log); + if (epVersion == EPVersions.EPV_06) { + result = await paymaster.signMultiTokenPaymaster(userOp, str, str1, entryPoint, paymasterAddress, gasToken, multiTokenOracles[chainId] ? multiTokenOracles[chainId][gasToken] : '', bundlerUrl, signer, networkConfig.MultiTokenPaymasterOracleUsed, NativeOracles[chainId], chainId, server.log); + } else { + result = await paymaster.signMultiTokenPaymasterV07(userOp, str, str1, entryPoint, paymasterAddress, gasToken, multiTokenOracles[chainId] ? multiTokenOracles[chainId][gasToken] : '', bundlerUrl, signer, networkConfig.MultiTokenPaymasterOracleUsed, NativeOracles[chainId], chainId, server.log); + } break; } case 'vps': { @@ -339,7 +359,7 @@ const paymasterRoutes: FastifyPluginAsync = async (server, const errorMessage: string = generateErrorMessage(ErrorMessage.NO_ACTIVE_SPONSORSHIP_POLICY_FOR_CURRENT_TIME, { walletAddress: apiKeyData?.walletAddress, epVersion: epVersion, chainId: chainId.chainId }); return reply.code(ReturnCode.FAILURE).send({ error: errorMessage }); } - + // get supported networks from sponsorshipPolicy const supportedNetworks: number[] | undefined | null = sponsorshipPolicy.enabledChains; if (!supportedNetworks || !supportedNetworks.includes(chainId.chainId)) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); @@ -368,43 +388,51 @@ const paymasterRoutes: FastifyPluginAsync = async (server, if (!contractWhitelistResult) throw new Error('Contract Method not whitelisted'); } - const globalWhitelistRecord = await server.whitelistRepository.findOneByApiKeyAndPolicyId(api_key); - if (!globalWhitelistRecord?.addresses.includes(userOp.sender)) { - const existingWhitelistRecord = await server.whitelistRepository.findOneByApiKeyAndPolicyId(api_key, sponsorshipPolicy.id); - if (!existingWhitelistRecord?.addresses.includes(userOp.sender)) throw new Error('This sender address has not been whitelisted yet'); + const isWhitelisted = await checkWhitelist(api_key, epVersion, userOp.sender, sponsorshipPolicy.id); + if (!isWhitelisted) { + throw new Error('This sender address has not been whitelisted yet'); } if (epVersion === EPVersions.EPV_06) { - if(!apiKeyEntity.verifyingPaymasters) { - return reply.code(ReturnCode.FAILURE).send({error: ErrorMessage.VP_NOT_DEPLOYED}); + if (!apiKeyEntity.verifyingPaymasters) { + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.VP_NOT_DEPLOYED }); } const paymasterAddr = JSON.parse(apiKeyEntity.verifyingPaymasters)[chainId.chainId]; - if(!paymasterAddr) { - return reply.code(ReturnCode.FAILURE).send({error: ErrorMessage.VP_NOT_DEPLOYED}); + if (!paymasterAddr) { + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.VP_NOT_DEPLOYED }); } result = await paymaster.signV06(userOp, str, str1, entryPoint, paymasterAddr, bundlerUrl, signer, estimate, server.log); } - else { + else if (epVersion === EPVersions.EPV_07) { if(!apiKeyEntity.verifyingPaymastersV2) { return reply.code(ReturnCode.FAILURE).send({error: ErrorMessage.VP_NOT_DEPLOYED}); } const paymasterAddr = JSON.parse(apiKeyEntity.verifyingPaymastersV2)[chainId.chainId]; - if(!paymasterAddr) { - return reply.code(ReturnCode.FAILURE).send({error: ErrorMessage.VP_NOT_DEPLOYED}); + if (!paymasterAddr) { + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.VP_NOT_DEPLOYED }); } result = await paymaster.signV07(userOp, str, str1, entryPoint, paymasterAddr, bundlerUrl, signer, estimate, server.log); + } else { + if (!apiKeyEntity.verifyingPaymastersV3) { + return reply.code(ReturnCode.FAILURE).send({error: ErrorMessage.VP_NOT_DEPLOYED}); + } + const paymasterAddr = JSON.parse(apiKeyEntity.verifyingPaymastersV3)[chainId.chainId]; + if (!paymasterAddr) { + return reply.code(ReturnCode.FAILURE).send({error: ErrorMessage.VP_NOT_DEPLOYED}); + } + result = await paymaster.signV08(userOp, str, str1, entryPoint, paymasterAddr, bundlerUrl, signer, estimate, server.log); } break; } case 'commonerc20': { - if (epVersion !== EPVersions.EPV_06) - throw new Error('Currently only EPV06 entryPoint address is supported') - const multiTokenRec = await server.multiTokenPaymasterRepository.findOneByChainIdAndTokenAddress(chainId, gasToken) + if (epVersion !== EPVersions.EPV_06 && epVersion !== EPVersions.EPV_07) + throw new Error(ErrorMessage.MTP_EP_SUPPORT) + const multiTokenRec = await server.multiTokenPaymasterRepository.findOneByChainIdEPVersionAndTokenAddress(chainId, gasToken, epVersion) if (multiTokenRec) { const date = new Date(); const provider = new providers.JsonRpcProvider(bundlerUrl); const commonPrivateKey = process.env.MTP_PRIVATE_KEY; - if (!commonPrivateKey) return reply.code(ReturnCode.FAILURE).send({error: ErrorMessage.NO_KEY_SET}) + if (!commonPrivateKey) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.NO_KEY_SET }) const signer = new Wallet(commonPrivateKey, provider) const validUntil = context.validUntil ? new Date(context.validUntil) : date; const validAfter = context.validAfter ? new Date(context.validAfter) : date; @@ -425,7 +453,11 @@ const paymasterRoutes: FastifyPluginAsync = async (server, throw new Error("Oracle is not Defined/Invalid"); if (networkConfig.MultiTokenPaymasterOracleUsed == "chainlink" && !NativeOracles[chainId]) throw new Error("Native Oracle address not set for this chainId") - result = await paymaster.signMultiTokenPaymaster(userOp, str, str1, entryPoint, multiTokenRec.paymasterAddress, gasToken, multiTokenRec.oracleAddress ?? '', bundlerUrl, signer, networkConfig.MultiTokenPaymasterOracleUsed, NativeOracles[chainId], chainId, server.log); + if (epVersion == EPVersions.EPV_06) { + result = await paymaster.signMultiTokenPaymaster(userOp, str, str1, entryPoint, multiTokenRec.paymasterAddress, gasToken, multiTokenRec.oracleAddress ?? '', bundlerUrl, signer, networkConfig.MultiTokenPaymasterOracleUsed, NativeOracles[chainId], chainId, server.log); + } else { + result = await paymaster.signMultiTokenPaymasterV07(userOp, str, str1, entryPoint, multiTokenRec.paymasterAddress, gasToken, multiTokenRec.oracleAddress ?? '', bundlerUrl, signer, networkConfig.MultiTokenPaymasterOracleUsed, NativeOracles[chainId], chainId, server.log); + } } else { return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_TOKEN }) } @@ -467,10 +499,10 @@ const paymasterRoutes: FastifyPluginAsync = async (server, for (const key of tokenOracleKeys) { tokenCache.push(paymaster.priceAndMetadata.get(key)) } - return reply.code(ReturnCode.SUCCESS).send({coingeckoCache, nativeTokenCache, tokenCache}) + return reply.code(ReturnCode.SUCCESS).send({ coingeckoCache, nativeTokenCache, tokenCache }) } catch (err) { request.log.error(err); - return reply.code(ReturnCode.FAILURE).send({error: err}) + return reply.code(ReturnCode.FAILURE).send({ error: err }) } }) @@ -558,6 +590,23 @@ const paymasterRoutes: FastifyPluginAsync = async (server, } return returnValue; } + + async function checkWhitelist(api_key: string, epVersion: EPVersions, senderAddress: string, policyId: number) { + const globalWhitelistRecord = await server.whitelistRepository.findOneByApiKeyAndPolicyId(api_key); + if (!globalWhitelistRecord?.addresses?.includes(senderAddress)) { + const existingWhitelistRecord = await server.whitelistRepository.findOneByApiKeyAndPolicyId(api_key, policyId); + if (!existingWhitelistRecord?.addresses?.includes(senderAddress)) { + const existingEpWhitelistRecord = await server.whitelistRepository.findOneByApiKeyEPVersionAndPolicyId(api_key, epVersion, policyId); + if (!existingEpWhitelistRecord?.addresses?.includes(senderAddress)) { + const existingEpWhitelistRecord2 = await server.whitelistRepository.findOneByApiKeyEPVersionAndPolicyId(api_key, epVersion); + if (!existingEpWhitelistRecord2?.addresses?.includes(senderAddress)) { + return false; + } + } + } + } + return true; + } }; export default paymasterRoutes; \ No newline at end of file diff --git a/backend/src/routes/pimlico-routes.ts b/backend/src/routes/token-routes.ts similarity index 93% rename from backend/src/routes/pimlico-routes.ts rename to backend/src/routes/token-routes.ts index 7522f53..5cdc7c0 100644 --- a/backend/src/routes/pimlico-routes.ts +++ b/backend/src/routes/token-routes.ts @@ -3,7 +3,7 @@ import { Type } from "@sinclair/typebox"; import { FastifyPluginAsync } from "fastify"; import { GetSecretValueCommand, SecretsManagerClient } from "@aws-sdk/client-secrets-manager"; import SupportedNetworks from "../../config.json" assert { type: "json" }; -import { PAYMASTER_ADDRESS } from "../constants/Pimlico.js"; +import { PAYMASTER_ADDRESS } from "../constants/Token.js"; import ErrorMessage from "../constants/ErrorMessage.js"; import ReturnCode from "../constants/ReturnCode.js"; import { decode } from "../utils/crypto.js"; @@ -11,7 +11,7 @@ import { printRequest, getNetworkConfig } from "../utils/common.js"; import { APIKey } from "../models/api-key.js"; import { ethers } from "ethers"; -const pimlicoRoutes: FastifyPluginAsync = async (server) => { +const tokenRoutes: FastifyPluginAsync = async (server) => { const prefixSecretId = 'arka_'; @@ -113,11 +113,9 @@ const pimlicoRoutes: FastifyPluginAsync = async (server) => { printRequest("/getAllCommonERC20PaymasterAddress", request, server.log); const query: any = request.query; const body: any = request.body; - const entryPoint = body.params[0]; - const api_key = query['apiKey'] ?? body.params[1]; + const api_key = query['apiKey'] ?? body.params[0]; if (!api_key || typeof(api_key) !== "string") return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) - if (!server.config.EPV_06.includes(entryPoint ?? '')) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_ENTRYPOINT }) const apiKeyData = await server.apiKeyRepository.findOneByApiKey(api_key); if (!apiKeyData) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) const multiTokenRec = await server.multiTokenPaymasterRepository.findAll(); @@ -126,7 +124,8 @@ const pimlicoRoutes: FastifyPluginAsync = async (server) => { paymasterAddress: record.paymasterAddress, gasToken: ethers.utils.getAddress(record.tokenAddress), chainId: record.chainId, - decimals: record.decimals + decimals: record.decimals, + epVersion: record.epVersion, } }); server.log.info(result, 'getAllCommonERC20PaymasterAddress Response sent: '); @@ -144,4 +143,4 @@ const pimlicoRoutes: FastifyPluginAsync = async (server) => { }; -export default pimlicoRoutes; +export default tokenRoutes; diff --git a/backend/src/routes/whitelist-routes.ts b/backend/src/routes/whitelist-routes.ts index e27cd73..b4adab3 100644 --- a/backend/src/routes/whitelist-routes.ts +++ b/backend/src/routes/whitelist-routes.ts @@ -10,13 +10,16 @@ import { decode } from "../utils/crypto.js"; import { printRequest, getNetworkConfig } from "../utils/common.js"; import { APIKey } from "../models/api-key.js"; import { ContractWhitelistDto } from "../types/contractWhitelist-dto.js"; +import { EPVersions } from "../types/sponsorship-policy-dto.js"; const whitelistRoutes: FastifyPluginAsync = async (server) => { - const paymaster = new Paymaster(server.config.FEE_MARKUP, server.config.MULTI_TOKEN_MARKUP, server.config.EP7_TOKEN_VGL, server.config.EP7_TOKEN_PGL, server.sequelize, server.config.MTP_VGL_MARKUP, server.config.EP7_PVGL); + const paymaster = new Paymaster(server.config.FEE_MARKUP, server.config.MULTI_TOKEN_MARKUP, server.config.EP7_TOKEN_VGL, server.config.EP7_TOKEN_PGL, server.sequelize, + server.config.MTP_VGL_MARKUP, server.config.EP7_PVGL, server.config.MTP_PVGL, server.config.MTP_PPGL, server.config.EP8_PVGL); const SUPPORTED_ENTRYPOINTS = { EPV_06: server.config.EPV_06, - EPV_07: server.config.EPV_07 + EPV_07: server.config.EPV_07, + EPV_08: server.config.EPV_08 } const prefixSecretId = 'arka_'; @@ -45,6 +48,9 @@ const whitelistRoutes: FastifyPluginAsync = async (server) => { } else { address = body.params?.[0]; policyId = body.params?.[1]; + if (policyId && isNaN(policyId)) { + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_DATA }); + } api_key = query['apiKey'] ?? body.params?.[2]; } if (!api_key || typeof(api_key) !== "string") @@ -150,6 +156,9 @@ const whitelistRoutes: FastifyPluginAsync = async (server) => { } else { address = body.params?.[0]; policyId = body.params?.[1]; + if (policyId && isNaN(policyId)) { + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_DATA }); + } chainId = query['chainId'] ?? body.params?.[2]; api_key = query['apiKey'] ?? body.params?.[3]; } @@ -262,6 +271,9 @@ const whitelistRoutes: FastifyPluginAsync = async (server) => { } else { accountAddress = body.params?.[0]; policyId = body.params?.[1]; + if (policyId && isNaN(policyId)) { + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_DATA }); + } chainId = query['chainId'] ?? body.params?.[2]; api_key = query['apiKey'] ?? body.params?.[3]; } @@ -344,6 +356,9 @@ const whitelistRoutes: FastifyPluginAsync = async (server) => { if (!body) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.MISSING_PARAMS }); const address = body.params?.[0]; const policyId = body.params?.[1]; + if (policyId && isNaN(policyId)) { + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_DATA }); + } const api_key = query['apiKey'] ?? body.params?.[2]; if (!api_key || typeof(api_key) !== "string") return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) @@ -379,22 +394,34 @@ const whitelistRoutes: FastifyPluginAsync = async (server) => { const policyRecord = await server.sponsorshipPolicyRepository.findOneById(policyId); if (!policyRecord || (policyRecord?.walletAddress !== signer.address)) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_SPONSORSHIP_POLICY_ID }) } - const existingWhitelistRecord = await server.whitelistRepository.findOneByApiKeyAndPolicyId(api_key, policyId); + const existingGlobalWhitelistRecord = await server.whitelistRepository.findOneByApiKeyAndPolicyId(api_key, policyId); + const existingWhitelistRecord = await server.whitelistRepository.findOneByApiKeyEPVersionAndPolicyId(api_key, EPVersions.EPV_07, policyId); - if (existingWhitelistRecord) { + if (existingWhitelistRecord || existingGlobalWhitelistRecord) { const toBeAdded: string[] = []; address.filter(ele => { - if (!existingWhitelistRecord.addresses.includes(ele)) toBeAdded.push(ele); + if (!existingWhitelistRecord?.addresses.includes(ele) && !existingGlobalWhitelistRecord?.addresses.includes(ele)) toBeAdded.push(ele); }); if (toBeAdded.length < 1) return reply.code(ReturnCode.CONFLICT).send({ error: ErrorMessage.ADDRESS_ALREADY_ADDED }); - const allAddresses = toBeAdded.concat(existingWhitelistRecord.addresses); - existingWhitelistRecord.addresses = allAddresses; - await server.whitelistRepository.updateOneById(existingWhitelistRecord); + if (existingWhitelistRecord) { + const allAddresses = toBeAdded.concat(existingWhitelistRecord.addresses); + existingWhitelistRecord.addresses = allAddresses; + await server.whitelistRepository.updateOneById(existingWhitelistRecord); + } else { + const addWhitelistDto = { + apiKey: api_key, + addresses: toBeAdded, + policyId: policyId ?? null, + epVersion: EPVersions.EPV_07 + } + await server.whitelistRepository.create(addWhitelistDto); + } } else { const addWhitelistDto = { apiKey: api_key, addresses: address, policyId: policyId ?? null, + epVersion: EPVersions.EPV_07 } await server.whitelistRepository.create(addWhitelistDto); } @@ -421,6 +448,9 @@ const whitelistRoutes: FastifyPluginAsync = async (server) => { if (!body) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.MISSING_PARAMS }); const address = body.params?.[0]; const policyId = body.params?.[1]; + if (policyId && isNaN(policyId)) { + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_DATA }); + } const chainId = query['chainId'] ?? body.params?.[2]; const api_key = query['apiKey'] ?? body.params?.[3]; if (!api_key || typeof(api_key) !== "string") @@ -457,21 +487,38 @@ const whitelistRoutes: FastifyPluginAsync = async (server) => { if (!networkConfig) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); const validAddresses = address.every(ethers.utils.isAddress); if (!validAddresses) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_ADDRESS_PASSSED }); - const existingWhitelistRecord = await server.whitelistRepository.findOneByApiKeyAndPolicyId(api_key, policyId); + const existingWhitelistRecord = await server.whitelistRepository.findOneByApiKeyEPVersionAndPolicyId(api_key, EPVersions.EPV_07, policyId); + const existingGlobalWhitelistRecord = await server.whitelistRepository.findOneByApiKeyAndPolicyId(api_key, policyId); + let isGlobal = false; - - if (existingWhitelistRecord) { + if (existingWhitelistRecord || existingGlobalWhitelistRecord) { const toBeRemoved: string[] = []; address.filter(ele => { - if (existingWhitelistRecord.addresses.includes(ele)) { + if (existingWhitelistRecord?.addresses.includes(ele)) { toBeRemoved.push(ele); existingWhitelistRecord.addresses.splice(existingWhitelistRecord.addresses.indexOf(ele), 1); } + if (existingGlobalWhitelistRecord?.addresses.includes(ele)) { + toBeRemoved.push(ele); + existingGlobalWhitelistRecord.addresses.splice(existingGlobalWhitelistRecord.addresses.indexOf(ele), 1); + isGlobal = true; + } }); if (toBeRemoved.length < 1) return reply.code(ReturnCode.CONFLICT).send({ error: ErrorMessage.ADDRESS_NOT_WHITELISTED }); - if (existingWhitelistRecord.addresses.length < 1) await server.whitelistRepository.deleteById(existingWhitelistRecord.id); - else await server.whitelistRepository.updateOneById(existingWhitelistRecord); + if (isGlobal) { + if (existingGlobalWhitelistRecord?.addresses.length == 0) { + await server.whitelistRepository.deleteById(existingGlobalWhitelistRecord.id); + } else if (existingGlobalWhitelistRecord){ + await server.whitelistRepository.updateOneById(existingGlobalWhitelistRecord); + } + } else { + if (existingWhitelistRecord?.addresses.length == 0) { + await server.whitelistRepository.deleteById(existingWhitelistRecord.id); + } else if (existingWhitelistRecord) { + await server.whitelistRepository.updateOneById(existingWhitelistRecord); + } + } } else { throw new Error(ErrorMessage.NO_WHITELIST_FOUND); } @@ -498,6 +545,9 @@ const whitelistRoutes: FastifyPluginAsync = async (server) => { if (!body) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.MISSING_PARAMS }); const accountAddress = body.params?.[0]; const policyId = body.params?.[1]; + if (policyId && isNaN(policyId)) { + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_DATA }); + } const chainId = query['chainId'] ?? body.params?.[2]; const api_key = query['apiKey'] ?? body.params?.[3]; if (!accountAddress || !ethers.utils.isAddress(accountAddress)) { @@ -535,12 +585,14 @@ const whitelistRoutes: FastifyPluginAsync = async (server) => { } const networkConfig = getNetworkConfig(chainId, supportedNetworks ?? '', SUPPORTED_ENTRYPOINTS.EPV_07); if (!networkConfig) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); - const existingWhitelistRecord = await server.whitelistRepository.findOneByApiKeyAndPolicyId(api_key, policyId); + const existingWhitelistRecord = await server.whitelistRepository.findOneByApiKeyEPVersionAndPolicyId(api_key, EPVersions.EPV_07, policyId); + const existingGlobalWhitelistRecord = await server.whitelistRepository.findOneByApiKeyAndPolicyId(api_key, policyId); - if (!existingWhitelistRecord) { + if (!existingWhitelistRecord && !existingGlobalWhitelistRecord) { throw new Error(ErrorMessage.NO_WHITELIST_FOUND); } - const result = { message: existingWhitelistRecord.addresses.includes(accountAddress) ? 'Already added' : 'Not added yet' } + const combinedRecord = { addresses: [...(existingWhitelistRecord?.addresses || []), ...(existingGlobalWhitelistRecord?.addresses || [])] } + const result = { message: combinedRecord.addresses.includes(accountAddress) ? 'Already added' : 'Not added yet' } server.log.info(result, 'Response sent: '); if (body.jsonrpc) return reply.code(ReturnCode.SUCCESS).send({ jsonrpc: body.jsonrpc, id: body.id, result, error: null }) @@ -561,6 +613,9 @@ const whitelistRoutes: FastifyPluginAsync = async (server) => { const body: any = request.body; const query: any = request.query; const policyId = body?.params?.[0]; + if (policyId && isNaN(policyId)) { + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_DATA }); + } const chainId = query['chainId'] ?? body?.params?.[1]; const api_key = query['apiKey'] ?? body?.params?.[2]; if (!api_key || typeof(api_key) !== "string") @@ -593,12 +648,16 @@ const whitelistRoutes: FastifyPluginAsync = async (server) => { } const networkConfig = getNetworkConfig(chainId, supportedNetworks ?? '', SUPPORTED_ENTRYPOINTS.EPV_07); if (!networkConfig) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); + // global whitelist const existingWhitelistRecord = await server.whitelistRepository.findOneByApiKeyAndPolicyId(api_key, policyId); - if (!existingWhitelistRecord) { + // EpVersion specific whitelist + const existingEpWhitelistRecord = await server.whitelistRepository.findOneByApiKeyEPVersionAndPolicyId(api_key, EPVersions.EPV_07, policyId); + + if (!existingWhitelistRecord && !existingEpWhitelistRecord) { throw new Error(ErrorMessage.NO_WHITELIST_FOUND); } - const result = { addresses: existingWhitelistRecord.addresses } + const result = { addresses: [...(existingWhitelistRecord?.addresses || []), ...(existingEpWhitelistRecord?.addresses || [])] } server.log.info(result, 'Response sent: '); if (body.jsonrpc) return reply.code(ReturnCode.SUCCESS).send({ jsonrpc: body.jsonrpc, id: body.id, result, error: null }) @@ -612,6 +671,326 @@ const whitelistRoutes: FastifyPluginAsync = async (server) => { } ) + server.post("/whitelist/v3", + async function (request, reply) { + try { + printRequest("/whitelist/v3", request, server.log); + const body: any = request.body; + const query: any = request.query; + if (!body) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.MISSING_PARAMS }); + const address = body.params?.[0]; + const policyId = body.params?.[1]; + if (policyId && isNaN(policyId)) { + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_DATA }); + } + const api_key = query['apiKey'] ?? body.params?.[2]; + if (!api_key || typeof(api_key) !== "string") + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) + let privateKey = ''; + const apiKeyEntity: APIKey | null = await server.apiKeyRepository.findOneByApiKey(api_key); + if (!apiKeyEntity) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) + if (!unsafeMode) { + const AWSresponse = await client.send( + new GetSecretValueCommand({ + SecretId: prefixSecretId + api_key, + }) + ); + const secrets = JSON.parse(AWSresponse.SecretString ?? '{}'); + if (!secrets['PRIVATE_KEY']) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) + privateKey = secrets['PRIVATE_KEY']; + } else { + privateKey = decode(apiKeyEntity.privateKey, server.config.HMAC_SECRET); + } + if (!privateKey) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) + if ( + !Array.isArray(address) || + address.length > 10 + ) { + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_DATA }); + } + if (server.config.SUPPORTED_NETWORKS == '' && !SupportedNetworks) { + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); + } + const validAddresses = address.every(ethers.utils.isAddress); + if (!validAddresses) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_ADDRESS_PASSSED }); + const signer = new Wallet(privateKey) + if (policyId) { + const policyRecord = await server.sponsorshipPolicyRepository.findOneById(policyId); + if (!policyRecord || (policyRecord?.walletAddress !== signer.address)) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_SPONSORSHIP_POLICY_ID }) + } + + const existingWhitelistRecord = await server.whitelistRepository.findOneByApiKeyEPVersionAndPolicyId(api_key, EPVersions.EPV_08, policyId); + const existingGlobalWhitelistRecord = await server.whitelistRepository.findOneByApiKeyAndPolicyId(api_key, policyId); + + if (existingWhitelistRecord || existingGlobalWhitelistRecord) { + const toBeAdded: string[] = []; + address.filter(ele => { + if (!existingWhitelistRecord?.addresses.includes(ele) && !existingGlobalWhitelistRecord?.addresses.includes(ele)) toBeAdded.push(ele); + }); + if (toBeAdded.length < 1) return reply.code(ReturnCode.CONFLICT).send({ error: ErrorMessage.ADDRESS_ALREADY_ADDED }); + if (!existingWhitelistRecord) { + const addWhitelistDto = { + apiKey: api_key, + addresses: toBeAdded, + policyId: policyId ?? null, + epVersion: EPVersions.EPV_08, + } + await server.whitelistRepository.create(addWhitelistDto); + } else { + const allAddresses = toBeAdded.concat(existingWhitelistRecord.addresses); + existingWhitelistRecord.addresses = allAddresses; + await server.whitelistRepository.updateOneById(existingWhitelistRecord); + } + } else { + const addWhitelistDto = { + apiKey: api_key, + addresses: address, + policyId: policyId ?? null, + epVersion: EPVersions.EPV_08, + } + await server.whitelistRepository.create(addWhitelistDto); + } + const result = { message: "Successfully whitelisted" } + server.log.info(result, 'Response sent: '); + if (body.jsonrpc) + return reply.code(ReturnCode.SUCCESS).send({ jsonrpc: body.jsonrpc, id: body.id, result, error: null }) + return reply.code(ReturnCode.SUCCESS).send(result); + } catch (err: any) { + request.log.error(err); + if (err.name == "ResourceNotFoundException") + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }); + return reply.code(ReturnCode.FAILURE).send({ error: err.message ?? ErrorMessage.FAILED_TO_PROCESS }) + } + } + ); + + server.post("/removeWhitelist/v3", + async function (request, reply) { + try { + printRequest("/removeWhitelist/v3", request, server.log); + const body: any = request.body; + const query: any = request.query; + if (!body) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.MISSING_PARAMS }); + const address = body.params?.[0]; + const policyId = body.params?.[1]; + if (policyId && isNaN(policyId)) { + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_DATA }); + } + const chainId = query['chainId'] ?? body.params?.[2]; + const api_key = query['apiKey'] ?? body.params?.[3]; + if (!api_key || typeof(api_key) !== "string") + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) + let privateKey = ''; + const apiKeyEntity: APIKey | null = await server.apiKeyRepository.findOneByApiKey(api_key); + if (!apiKeyEntity) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) + if (!unsafeMode) { + const AWSresponse = await client.send( + new GetSecretValueCommand({ + SecretId: prefixSecretId + api_key, + }) + ); + const secrets = JSON.parse(AWSresponse.SecretString ?? '{}'); + if (!secrets['PRIVATE_KEY']) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) + privateKey = secrets['PRIVATE_KEY']; + } else { + privateKey = decode(apiKeyEntity.privateKey, server.config.HMAC_SECRET); + } + const supportedNetworks = apiKeyEntity.supportedNetworks; + if (!privateKey) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) + if ( + !Array.isArray(address) || + address.length > 10 || + !chainId || + isNaN(chainId) + ) { + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_DATA }); + } + if (server.config.SUPPORTED_NETWORKS == '' && !SupportedNetworks) { + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); + } + const networkConfig = getNetworkConfig(chainId, supportedNetworks ?? '', SUPPORTED_ENTRYPOINTS.EPV_08); + if (!networkConfig) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); + const validAddresses = address.every(ethers.utils.isAddress); + if (!validAddresses) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_ADDRESS_PASSSED }); + const existingWhitelistRecord = await server.whitelistRepository.findOneByApiKeyEPVersionAndPolicyId(api_key, EPVersions.EPV_08, policyId); + const existingGlobalWhitelistRecord = await server.whitelistRepository.findOneByApiKeyAndPolicyId(api_key, policyId); + let isGlobal = false; + + if (existingWhitelistRecord || existingGlobalWhitelistRecord) { + const toBeRemoved: string[] = []; + address.filter(ele => { + if (existingWhitelistRecord?.addresses.includes(ele)) { + toBeRemoved.push(ele); + existingWhitelistRecord.addresses.splice(existingWhitelistRecord.addresses.indexOf(ele), 1); + } + if (existingGlobalWhitelistRecord?.addresses.includes(ele)) { + toBeRemoved.push(ele); + existingGlobalWhitelistRecord.addresses.splice(existingGlobalWhitelistRecord.addresses.indexOf(ele), 1); + isGlobal = true; + } + }); + if (toBeRemoved.length < 1) return reply.code(ReturnCode.CONFLICT).send({ error: ErrorMessage.ADDRESS_NOT_WHITELISTED }); + + if (isGlobal) { + if (existingGlobalWhitelistRecord?.addresses.length == 0) { + await server.whitelistRepository.deleteById(existingGlobalWhitelistRecord.id); + } else if (existingGlobalWhitelistRecord){ + await server.whitelistRepository.updateOneById(existingGlobalWhitelistRecord); + } + } else { + if (existingWhitelistRecord?.addresses.length == 0) { + await server.whitelistRepository.deleteById(existingWhitelistRecord.id); + } else if (existingWhitelistRecord) { + await server.whitelistRepository.updateOneById(existingWhitelistRecord); + } + } + } else { + throw new Error(ErrorMessage.NO_WHITELIST_FOUND); + } + const result = { message: "Successfully removed whitelisted addresses" } + server.log.info(result, 'Response sent: '); + if (body.jsonrpc) + return reply.code(ReturnCode.SUCCESS).send({ jsonrpc: body.jsonrpc, id: body.id, result, error: null }) + return reply.code(ReturnCode.SUCCESS).send(result); + } catch (err: any) { + request.log.error(err); + if (err.name == "ResourceNotFoundException") + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }); + return reply.code(ReturnCode.FAILURE).send({ error: err.message ?? ErrorMessage.FAILED_TO_PROCESS }) + } + } + ); + + server.post("/checkWhitelist/v3", + async function (request, reply) { + try { + printRequest("/checkWhitelist/v3", request, server.log); + const body: any = request.body; + const query: any = request.query; + if (!body) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.MISSING_PARAMS }); + const accountAddress = body.params?.[0]; + const policyId = body.params?.[1]; + if (policyId && isNaN(policyId)) { + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_DATA }); + } + const chainId = query['chainId'] ?? body.params?.[2]; + const api_key = query['apiKey'] ?? body.params?.[3]; + if (!accountAddress || !ethers.utils.isAddress(accountAddress)) { + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_DATA }); + } + if (!api_key || typeof(api_key) !== "string") + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) + let privateKey = ''; + const apiKeyEntity: APIKey | null = await server.apiKeyRepository.findOneByApiKey(api_key); + if (!apiKeyEntity) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) + if (!unsafeMode) { + const AWSresponse = await client.send( + new GetSecretValueCommand({ + SecretId: prefixSecretId + api_key, + }) + ); + const secrets = JSON.parse(AWSresponse.SecretString ?? '{}'); + if (!secrets['PRIVATE_KEY']) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) + privateKey = secrets['PRIVATE_KEY']; + } else { + privateKey = decode(apiKeyEntity.privateKey, server.config.HMAC_SECRET); + } + const supportedNetworks = apiKeyEntity.supportedNetworks; + if (!privateKey) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) + if ( + !accountAddress || + !ethers.utils.isAddress(accountAddress) || + !chainId || + isNaN(chainId) + ) { + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_DATA }); + } + if (server.config.SUPPORTED_NETWORKS == '' && !SupportedNetworks) { + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); + } + const networkConfig = getNetworkConfig(chainId, supportedNetworks ?? '', SUPPORTED_ENTRYPOINTS.EPV_08); + if (!networkConfig) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); + const existingWhitelistRecord = await server.whitelistRepository.findOneByApiKeyEPVersionAndPolicyId(api_key, EPVersions.EPV_08, policyId); + const existingGlobalWhitelistRecord = await server.whitelistRepository.findOneByApiKeyAndPolicyId(api_key, policyId); + + if (!existingWhitelistRecord && !existingGlobalWhitelistRecord) { + throw new Error(ErrorMessage.NO_WHITELIST_FOUND); + } + const combinedRecord = { addresses: [...(existingWhitelistRecord?.addresses || []), ...(existingGlobalWhitelistRecord?.addresses || [])] } + const result = { message: combinedRecord.addresses.includes(accountAddress) ? 'Already added' : 'Not added yet' } + server.log.info(result, 'Response sent: '); + if (body.jsonrpc) + return reply.code(ReturnCode.SUCCESS).send({ jsonrpc: body.jsonrpc, id: body.id, result, error: null }) + return reply.code(ReturnCode.SUCCESS).send(result); + } catch (err: any) { + request.log.error(err); + if (err.name == "ResourceNotFoundException") + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }); + return reply.code(ReturnCode.FAILURE).send({ error: err.message ?? ErrorMessage.FAILED_TO_PROCESS }) + } + } + ); + + server.post("/getAllWhitelist/v3", + async function (request, reply) { + try { + printRequest("/getAllWhitelist/v3", request, server.log); + const body: any = request.body; + const query: any = request.query; + const policyId = body?.params?.[0]; + if (policyId && isNaN(policyId)) { + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_DATA }); + } + const chainId = query['chainId'] ?? body?.params?.[1]; + const api_key = query['apiKey'] ?? body?.params?.[2]; + if (!api_key || typeof(api_key) !== "string") + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) + let privateKey = ''; + const apiKeyEntity: APIKey | null = await server.apiKeyRepository.findOneByApiKey(api_key); + if (!apiKeyEntity) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) + if (!unsafeMode) { + const AWSresponse = await client.send( + new GetSecretValueCommand({ + SecretId: prefixSecretId + api_key, + }) + ); + const secrets = JSON.parse(AWSresponse.SecretString ?? '{}'); + if (!secrets['PRIVATE_KEY']) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) + privateKey = secrets['PRIVATE_KEY']; + } else { + privateKey = decode(apiKeyEntity.privateKey, server.config.HMAC_SECRET); + } + if (!privateKey) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) + const supportedNetworks = apiKeyEntity.supportedNetworks; + if ( + !chainId || + isNaN(chainId) + ) { + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_DATA }); + } + if (server.config.SUPPORTED_NETWORKS == '' && !SupportedNetworks) { + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); + } + const networkConfig = getNetworkConfig(chainId, supportedNetworks ?? '', SUPPORTED_ENTRYPOINTS.EPV_08); + if (!networkConfig) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); + const existingGlobalWhitelistRecord = await server.whitelistRepository.findOneByApiKeyAndPolicyId(api_key, policyId); + const existingWhitelistRecord = await server.whitelistRepository.findOneByApiKeyEPVersionAndPolicyId(api_key, EPVersions.EPV_08, policyId); + if (!existingWhitelistRecord && !existingGlobalWhitelistRecord) { + throw new Error(ErrorMessage.NO_WHITELIST_FOUND); + } + const result = { addresses: [...(existingWhitelistRecord?.addresses || []), ...(existingGlobalWhitelistRecord?.addresses || [])] } + server.log.info(result, 'Response sent: '); + if (body.jsonrpc) + return reply.code(ReturnCode.SUCCESS).send({ jsonrpc: body.jsonrpc, id: body.id, result, error: null }) + return reply.code(ReturnCode.SUCCESS).send(result); + } catch (err: any) { + request.log.error(err); + if (err.name == "ResourceNotFoundException") + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }); + return reply.code(ReturnCode.FAILURE).send({ error: err.message ?? ErrorMessage.FAILED_TO_PROCESS }) + } + } ) + server.post("/whitelistContractAddress", async function (request, reply) { try { diff --git a/backend/src/server.ts b/backend/src/server.ts index ab00fab..44fe2bc 100644 --- a/backend/src/server.ts +++ b/backend/src/server.ts @@ -9,7 +9,7 @@ import fetch from 'node-fetch'; import sequelizePlugin from './plugins/sequelizePlugin.js'; import config from './plugins/config.js'; import EtherspotChainlinkOracleAbi from './abi/EtherspotChainlinkOracleAbi.js'; -import PimlicoAbi from './abi/PimlicoAbi.js'; +import ERC20PaymasterAbi from './abi/ERC20PaymasterAbi.js'; import PythOracleAbi from './abi/PythOracleAbi.js'; import { getNetworkConfig } from './utils/common.js'; import { checkDeposit } from './utils/monitorTokenPaymaster.js'; @@ -19,7 +19,7 @@ import adminRoutes from './routes/admin-routes.js'; import depositRoutes from './routes/deposit-route.js'; import metadataRoutes from './routes/metadata-routes.js'; import paymasterRoutes from './routes/paymaster-routes.js'; -import pimlicoRoutes from './routes/pimlico-routes.js'; +import tokenRoutes from './routes/token-routes.js'; import whitelistRoutes from './routes/whitelist-routes.js'; import sponsorshipPolicyRoutes from './routes/sponsorship-policy-routes.js'; import SupportedNetworks from "../config.json" assert { type: "json" }; @@ -61,7 +61,8 @@ const initializeServer = async (): Promise => { // Register the sequelizePlugin await server.register(sequelizePlugin); - const paymaster = new Paymaster(server.config.FEE_MARKUP, server.config.MULTI_TOKEN_MARKUP, server.config.EP7_TOKEN_VGL, server.config.EP7_TOKEN_PGL, server.sequelize, server.config.MTP_VGL_MARKUP, server.config.EP7_PVGL); + const paymaster = new Paymaster(server.config.FEE_MARKUP, server.config.MULTI_TOKEN_MARKUP, server.config.EP7_TOKEN_VGL, server.config.EP7_TOKEN_PGL, server.sequelize, + server.config.MTP_VGL_MARKUP, server.config.EP7_PVGL, server.config.MTP_PVGL, server.config.MTP_PPGL, server.config.EP8_PVGL); // Synchronize all models await server.sequelize.sync(); @@ -101,7 +102,7 @@ const initializeServer = async (): Promise => { await server.register(depositRoutes); - await server.register(pimlicoRoutes); + await server.register(tokenRoutes); await server.register(whitelistRoutes); @@ -161,7 +162,7 @@ const initializeServer = async (): Promise => { const provider = new providers.JsonRpcProvider(networkConfig.bundler); const signer = new ethers.Wallet(process.env.CRON_PRIVATE_KEY ?? '', provider); deployedPaymasters.forEach(async (deployedPaymaster) => { - const paymasterContract = new ethers.Contract(deployedPaymaster, PimlicoAbi, signer) + const paymasterContract = new ethers.Contract(deployedPaymaster, ERC20PaymasterAbi, signer) const pythMainnetChains = configData?.pythMainnetChainIds?.split(',') ?? []; const pythTestnetChains = configData?.pythTestnetChainIds?.split(',') ?? []; if (pythMainnetChains?.includes(chain) || pythTestnetChains?.includes(chain)) { @@ -262,7 +263,9 @@ const initializeServer = async (): Promise => { ) { const thresholdValue = network.thresholdValue ?? networkConfig.thresholdValue; const bundler = network.bundler ?? networkConfig.bundler; - checkDeposit(network.contracts.etherspotPaymasterAddress, bundler, process.env.WEBHOOK_URL, thresholdValue ?? '0.001', Number(network.chainId), server.log); + if (network.contracts?.etherspotPaymasterAddress) { + checkDeposit(network.contracts.etherspotPaymasterAddress, bundler, process.env.WEBHOOK_URL, thresholdValue ?? '0.001', Number(network.chainId), server.log); + } } } } @@ -305,7 +308,9 @@ const initializeServer = async (): Promise => { // checking deposit for epv6 native paymasters from default config.json. for (const network of SupportedNetworks) { - checkDeposit(network.contracts.etherspotPaymasterAddress, network.bundler, process.env.WEBHOOK_URL, network.thresholdValue ?? '0.001', Number(network.chainId), server.log); + if (network.contracts?.etherspotPaymasterAddress) { + checkDeposit(network.contracts.etherspotPaymasterAddress, network.bundler, process.env.WEBHOOK_URL, network.thresholdValue ?? '0.001', Number(network.chainId), server.log); + } } // Checking of Deposit on common multi token paymaster if any diff --git a/backend/src/types/sponsorship-policy-dto.ts b/backend/src/types/sponsorship-policy-dto.ts index c40f4c9..1529786 100644 --- a/backend/src/types/sponsorship-policy-dto.ts +++ b/backend/src/types/sponsorship-policy-dto.ts @@ -35,6 +35,7 @@ export interface SponsorshipPolicyDto { export enum EPVersions { EPV_06 = 'EPV_06', EPV_07 = 'EPV_07', + EPV_08 = 'EPV_08', // Add more versions here as needed } @@ -47,6 +48,8 @@ export function getEPVersion(value: string): EPVersions { return EPVersions.EPV_06; case 'EPV_07': return EPVersions.EPV_07; + case 'EPV_08': + return EPVersions.EPV_08; default: throw new Error('Unsupported EP version'); } @@ -59,6 +62,8 @@ export function getEPVersionString(value: EPVersions): string { return 'EPV_06'; case EPVersions.EPV_07: return 'EPV_07'; + case EPVersions.EPV_08: + return 'EPV_08'; default: throw new Error('Unsupported EP version'); } diff --git a/backend/src/types/whitelist-dto.ts b/backend/src/types/whitelist-dto.ts index e3bbc02..19a038d 100644 --- a/backend/src/types/whitelist-dto.ts +++ b/backend/src/types/whitelist-dto.ts @@ -1,5 +1,8 @@ +import { EPVersions } from "./sponsorship-policy-dto"; + export interface WhitelistDto { apiKey: string; addresses: string[]; policyId?: number; + epVersion?: EPVersions; } \ No newline at end of file