Skip to content

Commit

Permalink
PRO-2501-Arka_Contract_Events_Whitelist (#123)
Browse files Browse the repository at this point in the history
* added contract whitelist for etherspot prime and modular sdk

* updated package version

* changed parameter and API route path names
  • Loading branch information
vignesha22 authored Aug 12, 2024
1 parent 881c856 commit 9a796de
Show file tree
Hide file tree
Showing 17 changed files with 564 additions and 26 deletions.
4 changes: 2 additions & 2 deletions admin_frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion admin_frontend/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "admin_frontend",
"version": "1.3.1",
"version": "1.4.0",
"private": true,
"dependencies": {
"@emotion/react": "11.11.3",
Expand Down
52 changes: 52 additions & 0 deletions backend/migrations/2024080800001-create-contract-whitelist.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
const { Sequelize } = require('sequelize')

async function up({ context: queryInterface }) {
await queryInterface.createTable('contract_whitelist', {
ID: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false
},
WALLET_ADDRESS: {
type: Sequelize.TEXT,
allowNull: false,
},
CONTRACT_ADDRESS: {
type: Sequelize.TEXT,
allowNull: false,
},
FUNCTION_SELECTORS: {
type: Sequelize.ARRAY(Sequelize.TEXT),
allowNull: false,
},
ABI: {
type: Sequelize.TEXT,
allowNull: false,
},
CHAIN_ID: {
type: Sequelize.INTEGER,
allowNull: false,
},
CREATED_AT: {
type: Sequelize.DATE,
allowNull: false,
defaultValue: Sequelize.NOW
},
UPDATED_AT: {
type: Sequelize.DATE,
allowNull: false,
defaultValue: Sequelize.NOW
}
}, {
schema: process.env.DATABASE_SCHEMA_NAME
});
}
async function down({ context: queryInterface }) {
await queryInterface.dropTable({
tableName: 'contract_whitelist',
schema: process.env.DATABASE_SCHEMA_NAME
})
}

module.exports = { up, down }
11 changes: 11 additions & 0 deletions backend/migrations/2024080800002-update-apiKey.cjs
Original file line number Diff line number Diff line change
@@ -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 "CONTRACT_WHITELIST_MODE" text default false`);
}

async function down({ context: queryInterface }) {
await queryInterface.sequelize.query(`ALTER TABLE "${process.env.DATABASE_SCHEMA_NAME}".api_keys DROP COLUMN CONTRACT_WHITELIST_MODE;`);
}

module.exports = { up, down }
2 changes: 1 addition & 1 deletion backend/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "arka",
"version": "1.3.1",
"version": "1.4.0",
"description": "ARKA - (Albanian for Cashier's case) is the first open source Paymaster as a service software",
"type": "module",
"directories": {
Expand Down
5 changes: 5 additions & 0 deletions backend/src/constants/ErrorMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ export default {
ADDRESS_NOT_WHITELISTED: 'Addresses sent were not whitelisted',
NO_WHITELIST_FOUND: 'No whitelist were found on the given apiKey/policyId',
INVALID_ADDRESS_PASSSED: 'Invalid Address passed',
FAILED_TO_CREATE_CONTRACT_WHITELIST: 'Failed to create a record on contract whitelist',
FAILED_TO_UPDATE_CONTRACT_WHITELIST: 'Failed to update the record on contract whitelist',
FAILED_TO_DELETE_CONTRACT_WHITELIST: 'Failed to delete the record on contract whitelist',
NO_CONTRACT_WHITELIST_FOUND: 'No contract whitelist found for the given chainId, apiKey and contractAddress passed',
RECORD_ALREADY_EXISTS_CONTRACT_WHITELIST: 'Record already exists for the chainId, apiKey and contractAddress passed',
}

export function generateErrorMessage(template: string, values: { [key: string]: string | number }): string {
Expand Down
6 changes: 6 additions & 0 deletions backend/src/models/api-key.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export class APIKey extends Model {
public transactionLimit!: number;
public noOfTransactionsInAMonth?: number | null;
public indexerEndpoint?: string | null;
public contractWhitelistMode?: boolean | null;
public createdAt!: Date;
public updatedAt!: Date;
}
Expand Down Expand Up @@ -87,6 +88,11 @@ export function initializeAPIKeyModel(sequelize: Sequelize, schema: string) {
allowNull: true,
field: 'INDEXER_ENDPOINT'
},
contractWhitelistMode: {
type: DataTypes.BOOLEAN,
allowNull: true,
field: 'CONTRACT_WHITELIST_MODE'
},
createdAt: {
type: DataTypes.DATE,
allowNull: false,
Expand Down
71 changes: 71 additions & 0 deletions backend/src/models/contract-whitelist.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { Sequelize, DataTypes, Model } from 'sequelize';

export class ContractWhitelist extends Model {
public id!: number;
public walletAddress!: string;
public contractAddress!: string;
public functionSelectors!: string[];
public abi!: string;
public chainId!: number;
public createdAt!: Date;
public updatedAt!: Date;
}

export function initializeContractWhitelistModel(sequelize: Sequelize, schema: string) {
const initializedContractWhitelistModel = ContractWhitelist.init({
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
field: 'ID'
},
walletAddress: {
type: DataTypes.TEXT,
allowNull: false,
field: 'WALLET_ADDRESS'
},
contractAddress: {
type: DataTypes.TEXT,
allowNull: false,
field: 'CONTRACT_ADDRESS'
},
functionSelectors: {
type: DataTypes.ARRAY(DataTypes.TEXT),
allowNull: false,
field: 'FUNCTION_SELECTORS'
},
abi: {
type: DataTypes.TEXT,
allowNull: false,
field: 'ABI'
},
chainId: {
type: DataTypes.INTEGER,
allowNull: false,
field: 'CHAIN_ID'
},
createdAt: {
type: DataTypes.DATE,
allowNull: false,
field: 'CREATED_AT',
defaultValue: DataTypes.NOW,
},
updatedAt: {
type: DataTypes.DATE,
allowNull: false,
field: 'UPDATED_AT',
defaultValue: DataTypes.NOW,
},
}, {
tableName: 'contract_whitelist',
sequelize, // passing the `sequelize` instance is required
modelName: '',
timestamps: true, // enabling timestamps
createdAt: 'createdAt', // mapping 'createdAt' to 'CREATED_AT'
updatedAt: 'updatedAt', // mapping 'updatedAt' to 'UPDATED_AT'
freezeTableName: true,
schema: schema,
});

return initializedContractWhitelistModel;
}
14 changes: 9 additions & 5 deletions backend/src/paymaster/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,15 @@ import ERC20PaymasterV07Abi from '../abi/ERC20PaymasterV07Abi.js';
export class Paymaster {
feeMarkUp: BigNumber;
multiTokenMarkUp: number;
EP7_TOKEN_VGL: string;
EP7_TOKEN_PGL: string;

constructor(feeMarkUp: string, multiTokenMarkUp: string) {
constructor(feeMarkUp: string, multiTokenMarkUp: string, ep7TokenVGL: string, ep7TokenPGL: 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);
this.EP7_TOKEN_PGL = ep7TokenPGL;
this.EP7_TOKEN_VGL = ep7TokenVGL;
}

packUint (high128: BigNumberish, low128: BigNumberish): string {
Expand Down Expand Up @@ -325,8 +329,8 @@ export class Paymaster {
throw new Error(`The required token amount ${tokenAmountRequired.toString()} is more than what the sender has ${tokenBalance}`)
if (estimate) {
userOp.paymaster = paymasterAddress;
userOp.paymasterVerificationGasLimit = BigNumber.from('60000').toHexString();
userOp.paymasterPostOpGasLimit = BigNumber.from('100000').toHexString();
userOp.paymasterVerificationGasLimit = BigNumber.from(this.EP7_TOKEN_VGL).toHexString();
userOp.paymasterPostOpGasLimit = BigNumber.from(this.EP7_TOKEN_PGL).toHexString();
const response = await provider.send('eth_estimateUserOperationGas', [userOp, entryPoint]);
userOp.verificationGasLimit = response.verificationGasLimit;
userOp.callGasLimit = response.callGasLimit;
Expand All @@ -340,8 +344,8 @@ export class Paymaster {
preVerificationGas: BigNumber.from(userOp.preVerificationGas).toHexString(),
verificationGasLimit: BigNumber.from(userOp.verificationGasLimit).toHexString(),
callGasLimit: BigNumber.from(userOp.callGasLimit).toHexString(),
paymasterVerificationGasLimit: BigNumber.from('60000').toHexString(),
paymasterPostOpGasLimit: BigNumber.from('100000').toHexString()
paymasterVerificationGasLimit: BigNumber.from(this.EP7_TOKEN_VGL).toHexString(),
paymasterPostOpGasLimit: BigNumber.from(this.EP7_TOKEN_PGL).toHexString()
}
} else {
returnValue = {
Expand Down
4 changes: 4 additions & 0 deletions backend/src/plugins/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ 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'
})
);

Expand Down Expand Up @@ -64,6 +66,8 @@ const configPlugin: FastifyPluginAsync = async (server) => {
DATABASE_SCHEMA_NAME: process.env.DATABASE_SCHEMA_NAME ?? 'arka',
HMAC_SECRET: process.env.HMAC_SECRET ?? '',
UNSAFE_MODE: process.env.UNSAFE_MODE === 'true',
EP7_TOKEN_VGL: process.env.EP7_TOKEN_VGL ?? '90000',
EP7_TOKEN_PGL: process.env.EP7_TOKEN_PGL ?? '150000'
}

server.decorate("config", config);
Expand Down
6 changes: 6 additions & 0 deletions backend/src/plugins/sequelizePlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { ArkaConfigRepository } from "../repository/arka-config-repository.js";
import { SponsorshipPolicyRepository } from "../repository/sponsorship-policy-repository.js";
import { WhitelistRepository } from "../repository/whitelist-repository.js";
import { initializeArkaWhitelistModel } from "../models/whitelist.js";
import { ContractWhitelistRepository } from "../repository/contract-whitelist-repository.js";
import { initializeContractWhitelistModel } from "../models/contract-whitelist.js";
const pg = await import('pg');
const Client = pg.default.Client;

Expand Down Expand Up @@ -52,6 +54,7 @@ const sequelizePlugin: FastifyPluginAsync = async (server) => {
server.log.info(`Initialized APIKey model... ${sequelize.models.APIKey}`);
initializeSponsorshipPolicyModel(sequelize, server.config.DATABASE_SCHEMA_NAME);
initializeArkaWhitelistModel(sequelize, server.config.DATABASE_SCHEMA_NAME);
initializeContractWhitelistModel(sequelize, server.config.DATABASE_SCHEMA_NAME);
server.log.info('Initialized SponsorshipPolicy model...');

server.log.info('Initialized all models...');
Expand All @@ -66,6 +69,8 @@ const sequelizePlugin: FastifyPluginAsync = async (server) => {
server.decorate('sponsorshipPolicyRepository', sponsorshipPolicyRepository);
const whitelistRepository: WhitelistRepository = new WhitelistRepository(sequelize);
server.decorate('whitelistRepository', whitelistRepository);
const contractWhitelistRepository: ContractWhitelistRepository = new ContractWhitelistRepository(sequelize);
server.decorate('contractWhitelistRepository', contractWhitelistRepository);

server.log.info('decorated fastify server with models...');

Expand All @@ -83,6 +88,7 @@ declare module "fastify" {
arkaConfigRepository: ArkaConfigRepository;
sponsorshipPolicyRepository: SponsorshipPolicyRepository;
whitelistRepository: WhitelistRepository;
contractWhitelistRepository: ContractWhitelistRepository;
}
}

Expand Down
Loading

0 comments on commit 9a796de

Please sign in to comment.