From f960a59ab9134e45397a63546a6b490da8bc6c90 Mon Sep 17 00:00:00 2001 From: Abdul Ahad Date: Wed, 1 Feb 2023 19:55:24 +0500 Subject: [PATCH 01/36] redis host and port issue --- .env.example | 4 +++- README.md | 2 ++ src/services/job.service.ts | 7 ++++++- src/worker.ts | 6 ++++++ 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index 2c431d5..4dda265 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,6 @@ PORT=3000 MONGODB_URL=mongodb://127.0.0.1:27017/multiswap-node QUEUE=Transaction -GATEWAY_BACKEND_URL= \ No newline at end of file +GATEWAY_BACKEND_URL=https://api-leaderboard.dev.svcs.ferrumnetwork.io +REDIS_HOST=127.0.0.1 +REDIS_PORT=6379 \ No newline at end of file diff --git a/README.md b/README.md index ed70598..ab75d88 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ Redis Version `v7.0.8` Run the Redis Server in your machine by using `redis-server` command +Run this command `cp .env.example .env` to create .env file + Run `yarn` OR `yarn install` at the root of the repo Run `yarn dev` to run Server diff --git a/src/services/job.service.ts b/src/services/job.service.ts index 5ee4120..1ceffd4 100644 --- a/src/services/job.service.ts +++ b/src/services/job.service.ts @@ -3,7 +3,12 @@ import { JobRequestBody } from '../interfaces'; import dotenv from 'dotenv'; dotenv.config(); -const queue = new Queue(process.env.QUEUE as string); +const queue = new Queue(process.env.QUEUE as string, { + connection: { + host: process.env.REDIS_HOST as string, + port: Number(process.env.REDIS_PORT) as number, + }, +}); export const addJobs = async (jobBody: JobRequestBody): Promise => { const job = await queue.add(jobBody.name, jobBody); diff --git a/src/worker.ts b/src/worker.ts index 12b6959..cf61f4e 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -5,6 +5,12 @@ const worker = new Worker( process.env.QUEUE as string, async job => await web3Service.getTransactionReceipt(job.data.txId, job.data.rpcURL), + { + connection: { + host: process.env.REDIS_HOST as string, + port: Number(process.env.REDIS_PORT) as number, + }, + }, ); worker.on('completed', async job => { console.info(`${job.id} has completed!`); From 82d87b70265966d175451f6e776799b535623fd5 Mon Sep 17 00:00:00 2001 From: Zikriya Date: Wed, 1 Feb 2023 22:07:58 +0500 Subject: [PATCH 02/36] api createJobBySwapHash response have been modified --- src/controllers/job.controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/job.controller.ts b/src/controllers/job.controller.ts index 1ac2343..a843f11 100644 --- a/src/controllers/job.controller.ts +++ b/src/controllers/job.controller.ts @@ -4,7 +4,7 @@ import { jobService } from '../services'; export const createJob = async (req: Request, res: Response): Promise => { try { const job = await jobService.addJobs(req.body); - res.send(job.id); + res.send({jobId: job.id}); } catch (err) { console.error(err); } From ded4b24f5ba7c0bbdc927b3fd1d2b89235ec5bc2 Mon Sep 17 00:00:00 2001 From: Sheraz Riaz Date: Thu, 2 Feb 2023 15:08:13 +0500 Subject: [PATCH 03/36] dockerize app --- Dockerfile | 12 ++++++++++++ docker-compose.yaml | 48 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 Dockerfile create mode 100644 docker-compose.yaml diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..8eeb305 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +FROM node:18.12.1-alpine + +WORKDIR /app + +COPY . /app + +RUN mv .env.example .env +RUN yarn install + +EXPOSE 3000 + +CMD yarn dev diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..8cfb8e6 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,48 @@ +version: '3.8' +# networks: +# app-network: +# driver: bridge + +services: + redis: + container_name: redis + image: 'redis:7.0.8' + ports: + - '6379:6379' + command: redis-server --save 20 1 --loglevel warning + volumes: + - redis:/data + restart: + on-failure + # networks: + # - multiswap + expose: + - 6379 + multiswap_app: + build: + context: ./ + # target: development + container_name: multiswap_app + image: multiswap_app:latest + depends_on: + - redis + ports: + - 3000:3000 + environment: + REDIS_HOST: redis + REDIS_PORT: 6379 + + links: + - redis + restart: + on-failure +# networks: +# - multiswap + +# networks: +# multiswap: +# external: +# name: app +volumes: + redis: + driver: local \ No newline at end of file From 8c1ae9e7f5ae6236ad220b54b2db734679a00622 Mon Sep 17 00:00:00 2001 From: Zikriya Date: Fri, 3 Feb 2023 07:37:52 +0500 Subject: [PATCH 04/36] api updateTransactionJobStatus request body modified with transactionReceipt --- src/interfaces/job.interface.ts | 7 +++++++ src/services/axios.service.ts | 4 ++-- src/worker.ts | 4 ++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/interfaces/job.interface.ts b/src/interfaces/job.interface.ts index dfaf13f..c237ca7 100644 --- a/src/interfaces/job.interface.ts +++ b/src/interfaces/job.interface.ts @@ -1,5 +1,12 @@ +import { Transaction, TransactionReceipt } from '../interfaces'; + export interface JobRequestBody { name: string; rpcURL: string; txId: string; } + +export interface UpdateJobRequestBody { + transaction: Transaction; + transactionReceipt: TransactionReceipt; +} diff --git a/src/services/axios.service.ts b/src/services/axios.service.ts index b20cb9f..d6ab3b0 100644 --- a/src/services/axios.service.ts +++ b/src/services/axios.service.ts @@ -1,11 +1,11 @@ import axios from 'axios'; import dotenv from 'dotenv'; -import { Transaction } from '../interfaces'; +import { UpdateJobRequestBody } from '../interfaces'; dotenv.config(); export const updateTransactionJobStatus = async ( txHash: string, - body: Transaction, + body: UpdateJobRequestBody, ) => { const url = process.env.GATEWAY_BACKEND_URL; return axios.put( diff --git a/src/worker.ts b/src/worker.ts index cf61f4e..8b8f77b 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -18,7 +18,7 @@ worker.on('completed', async job => { job.data.txId, job.data.rpcURL, ); - axiosService.updateTransactionJobStatus(tx.hash, tx); + axiosService.updateTransactionJobStatus(tx.hash, {transaction:tx, transactionReceipt: job?.returnvalue}); }); worker.on('failed', async (job: any, err) => { @@ -27,7 +27,7 @@ worker.on('failed', async (job: any, err) => { job.data.txId, job.data.rpcURL, ); - axiosService.updateTransactionJobStatus(tx.hash, tx); + axiosService.updateTransactionJobStatus(tx.hash, {transaction:tx, transactionReceipt: job?.returnvalue}); }); export default worker; From ef0880d5c392cc29a26d6a60549effa9f8effbb9 Mon Sep 17 00:00:00 2001 From: Abdul Ahad Date: Fri, 17 Feb 2023 15:39:22 +0500 Subject: [PATCH 05/36] signature creation --- .env.example | 4 +- package.json | 1 + src/app.ts | 2 +- src/constants/FiberRouter.json | 839 +++++++++++++++++++++++++++++++++ src/constants/constants.ts | 2 + src/services/axios.service.ts | 6 +- src/services/web3.service.ts | 129 +++++ src/worker.ts | 17 +- 8 files changed, 986 insertions(+), 14 deletions(-) create mode 100644 src/constants/FiberRouter.json create mode 100644 src/constants/constants.ts diff --git a/.env.example b/.env.example index 4dda265..0133973 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,6 @@ PORT=3000 -MONGODB_URL=mongodb://127.0.0.1:27017/multiswap-node QUEUE=Transaction GATEWAY_BACKEND_URL=https://api-leaderboard.dev.svcs.ferrumnetwork.io REDIS_HOST=127.0.0.1 -REDIS_PORT=6379 \ No newline at end of file +REDIS_PORT=6379 +PRIVATE_KEY= \ No newline at end of file diff --git a/package.json b/package.json index 692c760..df64735 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "axios": "^1.2.6", "bullmq": "^3.5.11", "dotenv": "^16.0.3", + "ethers": "^5.6.3", "express": "^4.17.2", "web3": "^1.8.1" } diff --git a/src/app.ts b/src/app.ts index f574583..9f820ec 100644 --- a/src/app.ts +++ b/src/app.ts @@ -10,7 +10,7 @@ app.use(express.json()); app.use(express.urlencoded({ extended: true })); // v1 api routes -app.use('/', routes); +app.use('/api', routes); // send back a 404 error for any unknown api request app.use((req: Request, res: Response, next: NextFunction) => { diff --git a/src/constants/FiberRouter.json b/src/constants/FiberRouter.json new file mode 100644 index 0000000..ea95a6f --- /dev/null +++ b/src/constants/FiberRouter.json @@ -0,0 +1,839 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "FiberRouter", + "sourceName": "contracts/upgradeable-Bridge/FiberRouter.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "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": false, + "internalType": "address", + "name": "sourceToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "targetToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "sourceChainId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "targetChainId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "sourceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "sourceAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "targetAddress", + "type": "address" + } + ], + "name": "Swap", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + } + ], + "name": "getFee", + "outputs": [ + { + "internalType": "uint256", + "name": "_fee", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + } + ], + "name": "getFoundryTokenPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "string", + "name": "targetNetwork", + "type": "string" + }, + { + "internalType": "string", + "name": "targetToken", + "type": "string" + }, + { + "internalType": "string", + "name": "targetAddress", + "type": "string" + } + ], + "name": "nonEvmSwap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "swapRouter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountCrossMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "string", + "name": "crossTargetNetwork", + "type": "string" + }, + { + "internalType": "string", + "name": "crossTargetToken", + "type": "string" + }, + { + "internalType": "string", + "name": "receiver", + "type": "string" + } + ], + "name": "nonEvmSwapAndCross", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pool", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priceFeed", + "outputs": [ + { + "internalType": "contract AggregatorV3Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_fee", + "type": "uint256" + } + ], + "name": "setFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "address", + "name": "_oracleAddress", + "type": "address" + } + ], + "name": "setOracle", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_pool", + "type": "address" + } + ], + "name": "setPool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "targetNetwork", + "type": "uint256" + }, + { + "internalType": "address", + "name": "targetToken", + "type": "address" + }, + { + "internalType": "address", + "name": "targetAddress", + "type": "address" + } + ], + "name": "swap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "swapRouter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountCrossMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "crossTargetNetwork", + "type": "uint256" + }, + { + "internalType": "address", + "name": "crossTargetToken", + "type": "address" + } + ], + "name": "swapAndCross", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "swapRouter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountCrossMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "crossTargetNetwork", + "type": "uint256" + }, + { + "internalType": "address", + "name": "crossTargetToken", + "type": "address" + } + ], + "name": "swapAndCrossETH", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "address", + "name": "swapRouter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapETHForTokenSameNetwork", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "swapFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "address", + "name": "swapRouter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokenForETHSameNetwork", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "address", + "name": "swapRouter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokenForTokenSameNetwork", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "payee", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "address", + "name": "swapRouter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "withdrawAndSwap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "bridgeFoundry", + "type": "address" + }, + { + "internalType": "address", + "name": "targetFoundry", + "type": "address" + }, + { + "internalType": "address", + "name": "payee", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdrawAndSwapToFoundry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "payee", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "multiSignature", + "type": "bytes" + } + ], + "name": "withdrawSigned", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "address", + "name": "swapRouter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "multiSignature", + "type": "bytes" + } + ], + "name": "withdrawSignedAndSwap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "address", + "name": "swapRouter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "multiSignature", + "type": "bytes" + } + ], + "name": "withdrawSignedAndSwapETH", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "bridgeFoundry", + "type": "address" + }, + { + "internalType": "address", + "name": "targetFoundry", + "type": "address" + }, + { + "internalType": "address", + "name": "payee", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "multiSignature", + "type": "bytes" + } + ], + "name": "withdrawSignedAndSwapToFoundry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b50613438806100206000396000f3fe6080604052600436106101a05760003560e01c80638d6e9291116100ec578063bdb519b41161008a578063e450219d11610064578063e450219d146104c0578063e55156b5146104e0578063f1aaf72d14610500578063f2fde38b14610520576101a7565b8063bdb519b414610460578063c695e98e14610480578063d9caed12146104a0576101a7565b8063a6ae80e2116100c6578063a6ae80e2146103bd578063a81cb92e146103ea578063a9bc9bc31461040a578063b88c91481461042a576101a7565b80638d6e92911461035f5780638da5cb5b1461037f5780639f240e7d1461039d576101a7565b8063591a40c41161015957806373050a8a1161013357806373050a8a146102ea5780638129fc1c1461030a57806386214d801461031f5780638909d7331461033f576101a7565b8063591a40c4146102a25780635c38eb3a146102b5578063715018a6146102d5576101a7565b80630efe792d146101ac5780630f415c66146101df57806316f0115b146101f45780631fd48b9a1461022c5780633364a4e5146102625780634437152a14610282576101a7565b366101a757005b600080fd5b3480156101b857600080fd5b506101cc6101c73660046128e7565b610540565b6040519081526020015b60405180910390f35b6101f26101ed366004612ae0565b61068d565b005b34801561020057600080fd5b50609754610214906001600160a01b031681565b6040516001600160a01b0390911681526020016101d6565b34801561023857600080fd5b506102146102473660046128e7565b6098602052600090815260409020546001600160a01b031681565b34801561026e57600080fd5b506101f261027d366004612b63565b610850565b34801561028e57600080fd5b506101f261029d3660046128e7565b610af3565b6101f26102b0366004612c40565b610b5e565b3480156102c157600080fd5b506101f26102d036600461291f565b610d3f565b3480156102e157600080fd5b506101f2610dc1565b3480156102f657600080fd5b506101f2610305366004612cc5565b610dd5565b34801561031657600080fd5b506101f2610f03565b34801561032b57600080fd5b506101f261033a366004612ae0565b61101c565b34801561034b57600080fd5b506101f261035a366004612db7565b6112f1565b34801561036b57600080fd5b506101f261037a366004612a6c565b611417565b34801561038b57600080fd5b506065546001600160a01b0316610214565b3480156103a957600080fd5b506101f26103b8366004612b63565b61144f565b3480156103c957600080fd5b506101cc6103d83660046128e7565b60996020526000908152604090205481565b3480156103f657600080fd5b506101f2610405366004612d59565b6115f2565b34801561041657600080fd5b506101f2610425366004612957565b6117d8565b34801561043657600080fd5b506101cc6104453660046128e7565b6001600160a01b031660009081526099602052604090205490565b34801561046c57600080fd5b506101f261047b3660046129a7565b61189a565b34801561048c57600080fd5b506101f261049b366004612ae0565b611956565b3480156104ac57600080fd5b506101f26104bb366004612a2c565b611afa565b3480156104cc57600080fd5b506101f26104db366004612e75565b611b86565b3480156104ec57600080fd5b506101f26104fb366004612c15565b611cf9565b34801561050c57600080fd5b506101f261051b366004612ae0565b611d43565b34801561052c57600080fd5b506101f261053b3660046128e7565b611e1c565b6001600160a01b03808216600090815260986020526040808220548151633fabe5a360e21b815291519293849391169163feaf968c9160048083019260a0929190829003018186803b15801561059557600080fd5b505afa1580156105a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105cd9190612f3b565b5050506001600160a01b03808616600090815260986020908152604080832054815163313ce56760e01b81529151959750929550919092169263313ce56792600480840193919291829003018186803b15801561062957600080fd5b505afa15801561063d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106619190612f8a565b905061066e816012613372565b61067990600a61326b565b610683908361333c565b925050505b919050565b60003490506000876001600160a01b031663ad5c46486040518163ffffffff1660e01b815260040160206040518083038186803b1580156106cd57600080fd5b505afa1580156106e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107059190612903565b60405163095ea7b360e01b81529091506001600160a01b0382169063095ea7b390610736908b90869060040161305c565b602060405180830381600087803b15801561075057600080fd5b505af1158015610764573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107889190612f03565b50806001600160a01b031663d0e30db0836040518263ffffffff1660e01b81526004016000604051808303818588803b1580156107c457600080fd5b505af11580156107d8573d6000803e3d6000fd5b5050505050876001600160a01b0316635c11d795838888888e896040518763ffffffff1660e01b815260040161081396959493929190613192565b600060405180830381600087803b15801561082d57600080fd5b505af1158015610841573d6000803e3d6000fd5b50505050505050505050505050565b6001841161089a5760405162461bcd60e51b815260206004820152601260248201527110948e881c185d1a081d1bdbc81cda1bdc9d60721b60448201526064015b60405180910390fd5b6097546001600160a01b0316638d6e929186866000816108ca57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906108df91906128e7565b308a86866040518663ffffffff1660e01b8152600401610903959493929190613017565b602060405180830381600087803b15801561091d57600080fd5b505af1158015610931573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109559190612f23565b508484600081811061097757634e487b7160e01b600052603260045260246000fd5b905060200201602081019061098c91906128e7565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b1580156109cd57600080fd5b505afa1580156109e1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a059190612f23565b965084846000818110610a2857634e487b7160e01b600052603260045260246000fd5b9050602002016020810190610a3d91906128e7565b6001600160a01b031663095ea7b389896040518363ffffffff1660e01b8152600401610a6a92919061305c565b602060405180830381600087803b158015610a8457600080fd5b505af1158015610a98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610abc9190612f03565b50876001600160a01b0316635c11d795888888888e896040518763ffffffff1660e01b815260040161081396959493929190613192565b610afb611e92565b6001600160a01b038116610b3c5760405162461bcd60e51b815260206004820152600860248201526710985908141bdbdb60c21b6044820152606401610891565b609780546001600160a01b0319166001600160a01b0392909216919091179055565b46828114801590610bb65750816001600160a01b031686866000818110610b9557634e487b7160e01b600052603260045260246000fd5b9050602002016020810190610baa91906128e7565b6001600160a01b031614155b610bd25760405162461bcd60e51b815260040161089190613104565b60003490506000896001600160a01b031663ad5c46486040518163ffffffff1660e01b815260040160206040518083038186803b158015610c1257600080fd5b505afa158015610c26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4a9190612903565b60405163095ea7b360e01b81529091506001600160a01b0382169063095ea7b390610c7b908d90869060040161305c565b602060405180830381600087803b158015610c9557600080fd5b505af1158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd9190612f03565b50806001600160a01b031663d0e30db0836040518263ffffffff1660e01b81526004016000604051808303818588803b158015610d0957600080fd5b505af1158015610d1d573d6000803e3d6000fd5b5050505050610d33338b848c8c8c8c8c8c611eec565b50505050505050505050565b610d47611e92565b6001600160a01b038216610d6d5760405162461bcd60e51b8152600401610891906130e1565b6001600160a01b038116610d935760405162461bcd60e51b8152600401610891906130e1565b6001600160a01b03918216600090815260986020526040902080546001600160a01b03191691909216179055565b610dc9611e92565b610dd360006120be565b565b610dea6001600160a01b038616333087612110565b60975460405163095ea7b360e01b81526001600160a01b038781169263095ea7b392610e1e9290911690889060040161305c565b602060405180830381600087803b158015610e3857600080fd5b505af1158015610e4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e709190612f03565b5060975460405163ad93428360e01b81526001600160a01b039091169063ad93428390610ea99088908890889088908890600401613075565b602060405180830381600087803b158015610ec357600080fd5b505af1158015610ed7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610efb9190612f23565b505050505050565b600054610100900460ff1615808015610f235750600054600160ff909116105b80610f3d5750303b158015610f3d575060005460ff166001145b610fa05760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610891565b6000805460ff191660011790558015610fc3576000805461ff0019166101001790555b610fcb612168565b610fd3612197565b8015611019576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b600182116110615760405162461bcd60e51b815260206004820152601260248201527110948e881c185d1a081d1bdbc81cda1bdc9d60721b6044820152606401610891565b6097546001600160a01b031663d9caed12848460008161109157634e487b7160e01b600052603260045260246000fd5b90506020020160208101906110a691906128e7565b30886040518463ffffffff1660e01b81526004016110c693929190612ff3565b602060405180830381600087803b1580156110e057600080fd5b505af11580156110f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111189190612f23565b508282600081811061113a57634e487b7160e01b600052603260045260246000fd5b905060200201602081019061114f91906128e7565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b15801561119057600080fd5b505afa1580156111a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c89190612f23565b9450828260008181106111eb57634e487b7160e01b600052603260045260246000fd5b905060200201602081019061120091906128e7565b6001600160a01b031663095ea7b387876040518363ffffffff1660e01b815260040161122d92919061305c565b602060405180830381600087803b15801561124757600080fd5b505af115801561125b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127f9190612f03565b50604051635c11d79560e01b81526001600160a01b03871690635c11d795906112b69088908890889088908e908990600401613192565b600060405180830381600087803b1580156112d057600080fd5b505af11580156112e4573d6000803e3d6000fd5b5050505050505050505050565b6112f96121c6565b61133a8686600081811061131d57634e487b7160e01b600052603260045260246000fd5b905060200201602081019061133291906128e7565b33308b612220565b97508585600081811061135d57634e487b7160e01b600052603260045260246000fd5b905060200201602081019061137291906128e7565b6001600160a01b031663095ea7b38a8a6040518363ffffffff1660e01b815260040161139f92919061305c565b602060405180830381600087803b1580156113b957600080fd5b505af11580156113cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113f19190612f03565b50611403818a8a8a8a8a8a8a8a6123b0565b61140c60018055565b505050505050505050565b609754604051638d6e929160e01b81526001600160a01b0390911690638d6e929190610ea99088908890889088908890600401613017565b6097546001600160a01b0316638d6e9291868660008161147f57634e487b7160e01b600052603260045260246000fd5b905060200201602081019061149491906128e7565b308a86866040518663ffffffff1660e01b81526004016114b8959493929190613017565b602060405180830381600087803b1580156114d257600080fd5b505af11580156114e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061150a9190612f23565b508484600081811061152c57634e487b7160e01b600052603260045260246000fd5b905060200201602081019061154191906128e7565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b15801561158257600080fd5b505afa158015611596573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115ba9190612f23565b9650876001600160a01b031663791ac947888888888e896040518763ffffffff1660e01b815260040161081396959493929190613192565b468381148015906116155750826001600160a01b0316866001600160a01b031614155b6116315760405162461bcd60e51b815260040161089190613104565b6116466001600160a01b038716333088612110565b60975460405163095ea7b360e01b81526001600160a01b038881169263095ea7b39261167a9290911690899060040161305c565b602060405180830381600087803b15801561169457600080fd5b505af11580156116a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116cc9190612f03565b506097546040516352f9567d60e01b81526001600160a01b038881166004830152602482018890526044820187905285811660648301528481166084830152909116906352f9567d9060a401602060405180830381600087803b15801561173257600080fd5b505af1158015611746573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176a9190612f23565b50604080516001600160a01b0380891682528086166020830152468284015260608201879052608082018890523360a0830152841660c082015290517f36ae4b8940731f7c85b7db5bd11f85e01c730875f98d40504a8ae214393ca58d9181900360e00190a1505050505050565b60006117e385610540565b905060006117f085610540565b90506000816117ff848661333c565b6118099190613205565b609754604051636ce5768960e11b81529192506001600160a01b03169063d9caed129061183e90899089908690600401612ff3565b602060405180830381600087803b15801561185857600080fd5b505af115801561186c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118909190612f23565b5050505050505050565b60006118a587610540565b905060006118b287610540565b90506000816118c1848861333c565b6118cb9190613205565b609754604051638d6e929160e01b81529192506001600160a01b031690638d6e929190611904908b908b9086908b908b90600401613017565b602060405180830381600087803b15801561191e57600080fd5b505af1158015611932573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d339190612f23565b8282600081811061197757634e487b7160e01b600052603260045260246000fd5b905060200201602081019061198c91906128e7565b6001600160a01b03166323b872dd3330886040518463ffffffff1660e01b81526004016119bb93929190612ff3565b602060405180830381600087803b1580156119d557600080fd5b505af11580156119e9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a0d9190612f03565b5082826000818110611a2f57634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611a4491906128e7565b6001600160a01b031663095ea7b387876040518363ffffffff1660e01b8152600401611a7192919061305c565b602060405180830381600087803b158015611a8b57600080fd5b505af1158015611a9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ac39190612f03565b5060405163791ac94760e01b81526001600160a01b0387169063791ac947906112b69088908890889088908e908990600401613192565b609754604051636ce5768960e11b81526001600160a01b039091169063d9caed1290611b2e90869086908690600401612ff3565b602060405180830381600087803b158015611b4857600080fd5b505af1158015611b5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b809190612f23565b50505050565b611b8e6121c6565b46828114801590611be65750816001600160a01b031686866000818110611bc557634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611bda91906128e7565b6001600160a01b031614155b611c025760405162461bcd60e51b815260040161089190613104565b611c268686600081811061131d57634e487b7160e01b600052603260045260246000fd5b975085856000818110611c4957634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611c5e91906128e7565b6001600160a01b031663095ea7b38a8a6040518363ffffffff1660e01b8152600401611c8b92919061305c565b602060405180830381600087803b158015611ca557600080fd5b505af1158015611cb9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cdd9190612f03565b50611cef338a8a8a8a8a8a8a8a611eec565b5061189060018055565b611d01611e92565b6001600160a01b038216611d275760405162461bcd60e51b8152600401610891906130e1565b6001600160a01b03909116600090815260996020526040902055565b82826000818110611d6457634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611d7991906128e7565b6001600160a01b03166323b872dd3330886040518463ffffffff1660e01b8152600401611da893929190612ff3565b602060405180830381600087803b158015611dc257600080fd5b505af1158015611dd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dfa9190612f03565b50828260008181106111eb57634e487b7160e01b600052603260045260246000fd5b611e24611e92565b6001600160a01b038116611e895760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610891565b611019816120be565b6065546001600160a01b03163314610dd35760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610891565b604051635c11d79560e01b81526001600160a01b03891690635c11d79590611f22908a908a908a908a9030908b90600401613192565b600060405180830381600087803b158015611f3c57600080fd5b505af1158015611f50573d6000803e3d6000fd5b5060009250879150869050611f6660018261335b565b818110611f8357634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611f9891906128e7565b60975460405163095ea7b360e01b81529192506001600160a01b038084169263095ea7b392611fcd9216908b9060040161305c565b602060405180830381600087803b158015611fe757600080fd5b505af1158015611ffb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061201f9190612f03565b506097546040516352f9567d60e01b81526001600160a01b038381166004830152602482018a90526044820186905284811660648301528c81166084830152909116906352f9567d9060a4015b602060405180830381600087803b15801561208657600080fd5b505af115801561209a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e49190612f23565b606580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b611b80846323b872dd60e01b85858560405160240161213193929190612ff3565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612533565b600054610100900460ff1661218f5760405162461bcd60e51b815260040161089190613147565b610dd361260a565b600054610100900460ff166121be5760405162461bcd60e51b815260040161089190613147565b610dd361263a565b600260015414156122195760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610891565b6002600155565b6040516370a0823160e01b81526001600160a01b03838116600483015260009182918716906370a082319060240160206040518083038186803b15801561226657600080fd5b505afa15801561227a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061229e9190612f23565b90506122b56001600160a01b038716868686612110565b6040516370a0823160e01b81526001600160a01b038581166004830152600091908816906370a082319060240160206040518083038186803b1580156122fa57600080fd5b505afa15801561230e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123329190612f23565b905061233e828261335b565b9250838311156123a65760405162461bcd60e51b815260206004820152602d60248201527f53413a2061637475616c20616d6f756e74206c6172676572207468616e20747260448201526c185b9cd9995c88185b5bdd5b9d609a1b6064820152608401610891565b5050949350505050565b604051635c11d79560e01b81526001600160a01b03891690635c11d795906123e6908a908a908a908a9030908b90600401613192565b600060405180830381600087803b15801561240057600080fd5b505af1158015612414573d6000803e3d6000fd5b506000925087915086905061242a60018261335b565b81811061244757634e487b7160e01b600052603260045260246000fd5b905060200201602081019061245c91906128e7565b60975460405163095ea7b360e01b81529192506001600160a01b038084169263095ea7b3926124919216908b9060040161305c565b602060405180830381600087803b1580156124ab57600080fd5b505af11580156124bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124e39190612f03565b50609760009054906101000a90046001600160a01b03166001600160a01b031663ad934283828986868f6040518663ffffffff1660e01b815260040161206c959493929190613075565b60018055565b6000612588826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166126619092919063ffffffff16565b80519091501561260557808060200190518101906125a69190612f03565b6126055760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610891565b505050565b600054610100900460ff166126315760405162461bcd60e51b815260040161089190613147565b610dd3336120be565b600054610100900460ff1661252d5760405162461bcd60e51b815260040161089190613147565b6060612670848460008561267a565b90505b9392505050565b6060824710156126db5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610891565b600080866001600160a01b031685876040516126f79190612fd7565b60006040518083038185875af1925050503d8060008114612734576040519150601f19603f3d011682016040523d82523d6000602084013e612739565b606091505b509150915061274a87838387612757565b925050505b949350505050565b606083156127c35782516127bc576001600160a01b0385163b6127bc5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610891565b508161274f565b61274f83838151156127d85781518083602001fd5b8060405162461bcd60e51b815260040161089191906130ce565b8035610688816133ed565b60008083601f84011261280e578182fd5b50813567ffffffffffffffff811115612825578182fd5b602083019150836020808302850101111561283f57600080fd5b9250929050565b600082601f830112612856578081fd5b813567ffffffffffffffff80821115612871576128716133d7565b604051601f8301601f19908116603f01168101908282118183101715612899576128996133d7565b816040528381528660208588010111156128b1578485fd5b8360208701602083013792830160200193909352509392505050565b805169ffffffffffffffffffff8116811461068857600080fd5b6000602082840312156128f8578081fd5b8135612673816133ed565b600060208284031215612914578081fd5b8151612673816133ed565b60008060408385031215612931578081fd5b823561293c816133ed565b9150602083013561294c816133ed565b809150509250929050565b6000806000806080858703121561296c578182fd5b8435612977816133ed565b93506020850135612987816133ed565b92506040850135612997816133ed565b9396929550929360600135925050565b60008060008060008060c087890312156129bf578182fd5b86356129ca816133ed565b955060208701356129da816133ed565b945060408701356129ea816133ed565b9350606087013592506080870135915060a087013567ffffffffffffffff811115612a13578182fd5b612a1f89828a01612846565b9150509295509295509295565b600080600060608486031215612a40578283fd5b8335612a4b816133ed565b92506020840135612a5b816133ed565b929592945050506040919091013590565b600080600080600060a08688031215612a83578081fd5b8535612a8e816133ed565b94506020860135612a9e816133ed565b93506040860135925060608601359150608086013567ffffffffffffffff811115612ac7578182fd5b612ad388828901612846565b9150509295509295909350565b600080600080600080600060c0888a031215612afa578081fd5b8735612b05816133ed565b96506020880135612b15816133ed565b95506040880135945060608801359350608088013567ffffffffffffffff811115612b3e578182fd5b612b4a8a828b016127fd565b989b979a5095989497959660a090950135949350505050565b60008060008060008060008060006101008a8c031215612b81578283fd5b8935612b8c816133ed565b985060208a0135612b9c816133ed565b975060408a0135965060608a0135955060808a013567ffffffffffffffff80821115612bc6578485fd5b612bd28d838e016127fd565b909750955060a08c0135945060c08c0135935060e08c0135915080821115612bf8578283fd5b50612c058c828d01612846565b9150509295985092959850929598565b60008060408385031215612c27578182fd5b8235612c32816133ed565b946020939093013593505050565b600080600080600080600060c0888a031215612c5a578081fd5b8735612c65816133ed565b965060208801359550604088013567ffffffffffffffff811115612c87578182fd5b612c938a828b016127fd565b909650945050606088013592506080880135915060a0880135612cb5816133ed565b8091505092959891949750929550565b600080600080600060a08688031215612cdc578283fd5b8535612ce7816133ed565b945060208601359350604086013567ffffffffffffffff80821115612d0a578485fd5b612d1689838a01612846565b94506060880135915080821115612d2b578283fd5b612d3789838a01612846565b93506080880135915080821115612d4c578283fd5b50612ad388828901612846565b600080600080600060a08688031215612d70578283fd5b8535612d7b816133ed565b945060208601359350604086013592506060860135612d99816133ed565b91506080860135612da9816133ed565b809150509295509295909350565b60008060008060008060008060006101008a8c031215612dd5578283fd5b612dde8a6127f2565b985060208a0135975060408a0135965060608a013567ffffffffffffffff80821115612e08578485fd5b612e148d838e016127fd565b909850965060808c0135955060a08c0135915080821115612e33578485fd5b612e3f8d838e01612846565b945060c08c0135915080821115612e54578384fd5b612e608d838e01612846565b935060e08c0135915080821115612bf8578283fd5b60008060008060008060008060e0898b031215612e90578182fd5b8835612e9b816133ed565b97506020890135965060408901359550606089013567ffffffffffffffff811115612ec4578283fd5b612ed08b828c016127fd565b9096509450506080890135925060a0890135915060c0890135612ef2816133ed565b809150509295985092959890939650565b600060208284031215612f14578081fd5b81518015158114612673578182fd5b600060208284031215612f34578081fd5b5051919050565b600080600080600060a08688031215612f52578283fd5b612f5b866128cd565b9450602086015193506040860151925060608601519150612f7e608087016128cd565b90509295509295909350565b600060208284031215612f9b578081fd5b815160ff81168114612673578182fd5b60008151808452612fc3816020860160208601613395565b601f01601f19169290920160200192915050565b60008251612fe9818460208701613395565b9190910192915050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03868116825285166020820152604081018490526060810183905260a06080820181905260009061305190830184612fab565b979650505050505050565b6001600160a01b03929092168252602082015260400190565b600060018060a01b038716825285602083015260a0604083015261309c60a0830186612fab565b82810360608401526130ae8186612fab565b905082810360808401526130c28185612fab565b98975050505050505050565b6000602082526126736020830184612fab565b6020808252600990820152682130b2103a37b5b2b760b91b604082015260600190565b60208082526023908201527f4552524f523a2053414d4520544f4b454e20574954482053414d45204e4554576040820152624f524b60e81b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b868152602080820187905260a0604083018190528201859052600090869060c08401835b888110156131e45783356131c9816133ed565b6001600160a01b0316825292820192908201906001016131b6565b506001600160a01b0396909616606085015250505060800152949350505050565b60008261322057634e487b7160e01b81526012600452602481fd5b500490565b80825b60018086116132375750613262565b818704821115613249576132496133c1565b8086161561325657918102915b9490941c938002613228565b94509492505050565b600061267360001960ff85168460008261328757506001612673565b8161329457506000612673565b81600181146132aa57600281146132b4576132e1565b6001915050612673565b60ff8411156132c5576132c56133c1565b6001841b9150848211156132db576132db6133c1565b50612673565b5060208310610133831016604e8410600b8410161715613314575081810a8381111561330f5761330f6133c1565b612673565b6133218484846001613225565b808604821115613333576133336133c1565b02949350505050565b6000816000190483118215151615613356576133566133c1565b500290565b60008282101561336d5761336d6133c1565b500390565b600060ff821660ff84168082101561338c5761338c6133c1565b90039392505050565b60005b838110156133b0578181015183820152602001613398565b83811115611b805750506000910152565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461101957600080fdfea264697066735822122096063dd122c7f58c9c4b2090fd7f7b0b39209d110e4417f42bb29e8ffefe379f64736f6c63430008020033", + "deployedBytecode": "0x6080604052600436106101a05760003560e01c80638d6e9291116100ec578063bdb519b41161008a578063e450219d11610064578063e450219d146104c0578063e55156b5146104e0578063f1aaf72d14610500578063f2fde38b14610520576101a7565b8063bdb519b414610460578063c695e98e14610480578063d9caed12146104a0576101a7565b8063a6ae80e2116100c6578063a6ae80e2146103bd578063a81cb92e146103ea578063a9bc9bc31461040a578063b88c91481461042a576101a7565b80638d6e92911461035f5780638da5cb5b1461037f5780639f240e7d1461039d576101a7565b8063591a40c41161015957806373050a8a1161013357806373050a8a146102ea5780638129fc1c1461030a57806386214d801461031f5780638909d7331461033f576101a7565b8063591a40c4146102a25780635c38eb3a146102b5578063715018a6146102d5576101a7565b80630efe792d146101ac5780630f415c66146101df57806316f0115b146101f45780631fd48b9a1461022c5780633364a4e5146102625780634437152a14610282576101a7565b366101a757005b600080fd5b3480156101b857600080fd5b506101cc6101c73660046128e7565b610540565b6040519081526020015b60405180910390f35b6101f26101ed366004612ae0565b61068d565b005b34801561020057600080fd5b50609754610214906001600160a01b031681565b6040516001600160a01b0390911681526020016101d6565b34801561023857600080fd5b506102146102473660046128e7565b6098602052600090815260409020546001600160a01b031681565b34801561026e57600080fd5b506101f261027d366004612b63565b610850565b34801561028e57600080fd5b506101f261029d3660046128e7565b610af3565b6101f26102b0366004612c40565b610b5e565b3480156102c157600080fd5b506101f26102d036600461291f565b610d3f565b3480156102e157600080fd5b506101f2610dc1565b3480156102f657600080fd5b506101f2610305366004612cc5565b610dd5565b34801561031657600080fd5b506101f2610f03565b34801561032b57600080fd5b506101f261033a366004612ae0565b61101c565b34801561034b57600080fd5b506101f261035a366004612db7565b6112f1565b34801561036b57600080fd5b506101f261037a366004612a6c565b611417565b34801561038b57600080fd5b506065546001600160a01b0316610214565b3480156103a957600080fd5b506101f26103b8366004612b63565b61144f565b3480156103c957600080fd5b506101cc6103d83660046128e7565b60996020526000908152604090205481565b3480156103f657600080fd5b506101f2610405366004612d59565b6115f2565b34801561041657600080fd5b506101f2610425366004612957565b6117d8565b34801561043657600080fd5b506101cc6104453660046128e7565b6001600160a01b031660009081526099602052604090205490565b34801561046c57600080fd5b506101f261047b3660046129a7565b61189a565b34801561048c57600080fd5b506101f261049b366004612ae0565b611956565b3480156104ac57600080fd5b506101f26104bb366004612a2c565b611afa565b3480156104cc57600080fd5b506101f26104db366004612e75565b611b86565b3480156104ec57600080fd5b506101f26104fb366004612c15565b611cf9565b34801561050c57600080fd5b506101f261051b366004612ae0565b611d43565b34801561052c57600080fd5b506101f261053b3660046128e7565b611e1c565b6001600160a01b03808216600090815260986020526040808220548151633fabe5a360e21b815291519293849391169163feaf968c9160048083019260a0929190829003018186803b15801561059557600080fd5b505afa1580156105a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105cd9190612f3b565b5050506001600160a01b03808616600090815260986020908152604080832054815163313ce56760e01b81529151959750929550919092169263313ce56792600480840193919291829003018186803b15801561062957600080fd5b505afa15801561063d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106619190612f8a565b905061066e816012613372565b61067990600a61326b565b610683908361333c565b925050505b919050565b60003490506000876001600160a01b031663ad5c46486040518163ffffffff1660e01b815260040160206040518083038186803b1580156106cd57600080fd5b505afa1580156106e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107059190612903565b60405163095ea7b360e01b81529091506001600160a01b0382169063095ea7b390610736908b90869060040161305c565b602060405180830381600087803b15801561075057600080fd5b505af1158015610764573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107889190612f03565b50806001600160a01b031663d0e30db0836040518263ffffffff1660e01b81526004016000604051808303818588803b1580156107c457600080fd5b505af11580156107d8573d6000803e3d6000fd5b5050505050876001600160a01b0316635c11d795838888888e896040518763ffffffff1660e01b815260040161081396959493929190613192565b600060405180830381600087803b15801561082d57600080fd5b505af1158015610841573d6000803e3d6000fd5b50505050505050505050505050565b6001841161089a5760405162461bcd60e51b815260206004820152601260248201527110948e881c185d1a081d1bdbc81cda1bdc9d60721b60448201526064015b60405180910390fd5b6097546001600160a01b0316638d6e929186866000816108ca57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906108df91906128e7565b308a86866040518663ffffffff1660e01b8152600401610903959493929190613017565b602060405180830381600087803b15801561091d57600080fd5b505af1158015610931573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109559190612f23565b508484600081811061097757634e487b7160e01b600052603260045260246000fd5b905060200201602081019061098c91906128e7565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b1580156109cd57600080fd5b505afa1580156109e1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a059190612f23565b965084846000818110610a2857634e487b7160e01b600052603260045260246000fd5b9050602002016020810190610a3d91906128e7565b6001600160a01b031663095ea7b389896040518363ffffffff1660e01b8152600401610a6a92919061305c565b602060405180830381600087803b158015610a8457600080fd5b505af1158015610a98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610abc9190612f03565b50876001600160a01b0316635c11d795888888888e896040518763ffffffff1660e01b815260040161081396959493929190613192565b610afb611e92565b6001600160a01b038116610b3c5760405162461bcd60e51b815260206004820152600860248201526710985908141bdbdb60c21b6044820152606401610891565b609780546001600160a01b0319166001600160a01b0392909216919091179055565b46828114801590610bb65750816001600160a01b031686866000818110610b9557634e487b7160e01b600052603260045260246000fd5b9050602002016020810190610baa91906128e7565b6001600160a01b031614155b610bd25760405162461bcd60e51b815260040161089190613104565b60003490506000896001600160a01b031663ad5c46486040518163ffffffff1660e01b815260040160206040518083038186803b158015610c1257600080fd5b505afa158015610c26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4a9190612903565b60405163095ea7b360e01b81529091506001600160a01b0382169063095ea7b390610c7b908d90869060040161305c565b602060405180830381600087803b158015610c9557600080fd5b505af1158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd9190612f03565b50806001600160a01b031663d0e30db0836040518263ffffffff1660e01b81526004016000604051808303818588803b158015610d0957600080fd5b505af1158015610d1d573d6000803e3d6000fd5b5050505050610d33338b848c8c8c8c8c8c611eec565b50505050505050505050565b610d47611e92565b6001600160a01b038216610d6d5760405162461bcd60e51b8152600401610891906130e1565b6001600160a01b038116610d935760405162461bcd60e51b8152600401610891906130e1565b6001600160a01b03918216600090815260986020526040902080546001600160a01b03191691909216179055565b610dc9611e92565b610dd360006120be565b565b610dea6001600160a01b038616333087612110565b60975460405163095ea7b360e01b81526001600160a01b038781169263095ea7b392610e1e9290911690889060040161305c565b602060405180830381600087803b158015610e3857600080fd5b505af1158015610e4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e709190612f03565b5060975460405163ad93428360e01b81526001600160a01b039091169063ad93428390610ea99088908890889088908890600401613075565b602060405180830381600087803b158015610ec357600080fd5b505af1158015610ed7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610efb9190612f23565b505050505050565b600054610100900460ff1615808015610f235750600054600160ff909116105b80610f3d5750303b158015610f3d575060005460ff166001145b610fa05760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610891565b6000805460ff191660011790558015610fc3576000805461ff0019166101001790555b610fcb612168565b610fd3612197565b8015611019576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b600182116110615760405162461bcd60e51b815260206004820152601260248201527110948e881c185d1a081d1bdbc81cda1bdc9d60721b6044820152606401610891565b6097546001600160a01b031663d9caed12848460008161109157634e487b7160e01b600052603260045260246000fd5b90506020020160208101906110a691906128e7565b30886040518463ffffffff1660e01b81526004016110c693929190612ff3565b602060405180830381600087803b1580156110e057600080fd5b505af11580156110f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111189190612f23565b508282600081811061113a57634e487b7160e01b600052603260045260246000fd5b905060200201602081019061114f91906128e7565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b15801561119057600080fd5b505afa1580156111a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c89190612f23565b9450828260008181106111eb57634e487b7160e01b600052603260045260246000fd5b905060200201602081019061120091906128e7565b6001600160a01b031663095ea7b387876040518363ffffffff1660e01b815260040161122d92919061305c565b602060405180830381600087803b15801561124757600080fd5b505af115801561125b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127f9190612f03565b50604051635c11d79560e01b81526001600160a01b03871690635c11d795906112b69088908890889088908e908990600401613192565b600060405180830381600087803b1580156112d057600080fd5b505af11580156112e4573d6000803e3d6000fd5b5050505050505050505050565b6112f96121c6565b61133a8686600081811061131d57634e487b7160e01b600052603260045260246000fd5b905060200201602081019061133291906128e7565b33308b612220565b97508585600081811061135d57634e487b7160e01b600052603260045260246000fd5b905060200201602081019061137291906128e7565b6001600160a01b031663095ea7b38a8a6040518363ffffffff1660e01b815260040161139f92919061305c565b602060405180830381600087803b1580156113b957600080fd5b505af11580156113cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113f19190612f03565b50611403818a8a8a8a8a8a8a8a6123b0565b61140c60018055565b505050505050505050565b609754604051638d6e929160e01b81526001600160a01b0390911690638d6e929190610ea99088908890889088908890600401613017565b6097546001600160a01b0316638d6e9291868660008161147f57634e487b7160e01b600052603260045260246000fd5b905060200201602081019061149491906128e7565b308a86866040518663ffffffff1660e01b81526004016114b8959493929190613017565b602060405180830381600087803b1580156114d257600080fd5b505af11580156114e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061150a9190612f23565b508484600081811061152c57634e487b7160e01b600052603260045260246000fd5b905060200201602081019061154191906128e7565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b15801561158257600080fd5b505afa158015611596573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115ba9190612f23565b9650876001600160a01b031663791ac947888888888e896040518763ffffffff1660e01b815260040161081396959493929190613192565b468381148015906116155750826001600160a01b0316866001600160a01b031614155b6116315760405162461bcd60e51b815260040161089190613104565b6116466001600160a01b038716333088612110565b60975460405163095ea7b360e01b81526001600160a01b038881169263095ea7b39261167a9290911690899060040161305c565b602060405180830381600087803b15801561169457600080fd5b505af11580156116a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116cc9190612f03565b506097546040516352f9567d60e01b81526001600160a01b038881166004830152602482018890526044820187905285811660648301528481166084830152909116906352f9567d9060a401602060405180830381600087803b15801561173257600080fd5b505af1158015611746573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176a9190612f23565b50604080516001600160a01b0380891682528086166020830152468284015260608201879052608082018890523360a0830152841660c082015290517f36ae4b8940731f7c85b7db5bd11f85e01c730875f98d40504a8ae214393ca58d9181900360e00190a1505050505050565b60006117e385610540565b905060006117f085610540565b90506000816117ff848661333c565b6118099190613205565b609754604051636ce5768960e11b81529192506001600160a01b03169063d9caed129061183e90899089908690600401612ff3565b602060405180830381600087803b15801561185857600080fd5b505af115801561186c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118909190612f23565b5050505050505050565b60006118a587610540565b905060006118b287610540565b90506000816118c1848861333c565b6118cb9190613205565b609754604051638d6e929160e01b81529192506001600160a01b031690638d6e929190611904908b908b9086908b908b90600401613017565b602060405180830381600087803b15801561191e57600080fd5b505af1158015611932573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d339190612f23565b8282600081811061197757634e487b7160e01b600052603260045260246000fd5b905060200201602081019061198c91906128e7565b6001600160a01b03166323b872dd3330886040518463ffffffff1660e01b81526004016119bb93929190612ff3565b602060405180830381600087803b1580156119d557600080fd5b505af11580156119e9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a0d9190612f03565b5082826000818110611a2f57634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611a4491906128e7565b6001600160a01b031663095ea7b387876040518363ffffffff1660e01b8152600401611a7192919061305c565b602060405180830381600087803b158015611a8b57600080fd5b505af1158015611a9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ac39190612f03565b5060405163791ac94760e01b81526001600160a01b0387169063791ac947906112b69088908890889088908e908990600401613192565b609754604051636ce5768960e11b81526001600160a01b039091169063d9caed1290611b2e90869086908690600401612ff3565b602060405180830381600087803b158015611b4857600080fd5b505af1158015611b5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b809190612f23565b50505050565b611b8e6121c6565b46828114801590611be65750816001600160a01b031686866000818110611bc557634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611bda91906128e7565b6001600160a01b031614155b611c025760405162461bcd60e51b815260040161089190613104565b611c268686600081811061131d57634e487b7160e01b600052603260045260246000fd5b975085856000818110611c4957634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611c5e91906128e7565b6001600160a01b031663095ea7b38a8a6040518363ffffffff1660e01b8152600401611c8b92919061305c565b602060405180830381600087803b158015611ca557600080fd5b505af1158015611cb9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cdd9190612f03565b50611cef338a8a8a8a8a8a8a8a611eec565b5061189060018055565b611d01611e92565b6001600160a01b038216611d275760405162461bcd60e51b8152600401610891906130e1565b6001600160a01b03909116600090815260996020526040902055565b82826000818110611d6457634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611d7991906128e7565b6001600160a01b03166323b872dd3330886040518463ffffffff1660e01b8152600401611da893929190612ff3565b602060405180830381600087803b158015611dc257600080fd5b505af1158015611dd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dfa9190612f03565b50828260008181106111eb57634e487b7160e01b600052603260045260246000fd5b611e24611e92565b6001600160a01b038116611e895760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610891565b611019816120be565b6065546001600160a01b03163314610dd35760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610891565b604051635c11d79560e01b81526001600160a01b03891690635c11d79590611f22908a908a908a908a9030908b90600401613192565b600060405180830381600087803b158015611f3c57600080fd5b505af1158015611f50573d6000803e3d6000fd5b5060009250879150869050611f6660018261335b565b818110611f8357634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611f9891906128e7565b60975460405163095ea7b360e01b81529192506001600160a01b038084169263095ea7b392611fcd9216908b9060040161305c565b602060405180830381600087803b158015611fe757600080fd5b505af1158015611ffb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061201f9190612f03565b506097546040516352f9567d60e01b81526001600160a01b038381166004830152602482018a90526044820186905284811660648301528c81166084830152909116906352f9567d9060a4015b602060405180830381600087803b15801561208657600080fd5b505af115801561209a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e49190612f23565b606580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b611b80846323b872dd60e01b85858560405160240161213193929190612ff3565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612533565b600054610100900460ff1661218f5760405162461bcd60e51b815260040161089190613147565b610dd361260a565b600054610100900460ff166121be5760405162461bcd60e51b815260040161089190613147565b610dd361263a565b600260015414156122195760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610891565b6002600155565b6040516370a0823160e01b81526001600160a01b03838116600483015260009182918716906370a082319060240160206040518083038186803b15801561226657600080fd5b505afa15801561227a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061229e9190612f23565b90506122b56001600160a01b038716868686612110565b6040516370a0823160e01b81526001600160a01b038581166004830152600091908816906370a082319060240160206040518083038186803b1580156122fa57600080fd5b505afa15801561230e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123329190612f23565b905061233e828261335b565b9250838311156123a65760405162461bcd60e51b815260206004820152602d60248201527f53413a2061637475616c20616d6f756e74206c6172676572207468616e20747260448201526c185b9cd9995c88185b5bdd5b9d609a1b6064820152608401610891565b5050949350505050565b604051635c11d79560e01b81526001600160a01b03891690635c11d795906123e6908a908a908a908a9030908b90600401613192565b600060405180830381600087803b15801561240057600080fd5b505af1158015612414573d6000803e3d6000fd5b506000925087915086905061242a60018261335b565b81811061244757634e487b7160e01b600052603260045260246000fd5b905060200201602081019061245c91906128e7565b60975460405163095ea7b360e01b81529192506001600160a01b038084169263095ea7b3926124919216908b9060040161305c565b602060405180830381600087803b1580156124ab57600080fd5b505af11580156124bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124e39190612f03565b50609760009054906101000a90046001600160a01b03166001600160a01b031663ad934283828986868f6040518663ffffffff1660e01b815260040161206c959493929190613075565b60018055565b6000612588826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166126619092919063ffffffff16565b80519091501561260557808060200190518101906125a69190612f03565b6126055760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610891565b505050565b600054610100900460ff166126315760405162461bcd60e51b815260040161089190613147565b610dd3336120be565b600054610100900460ff1661252d5760405162461bcd60e51b815260040161089190613147565b6060612670848460008561267a565b90505b9392505050565b6060824710156126db5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610891565b600080866001600160a01b031685876040516126f79190612fd7565b60006040518083038185875af1925050503d8060008114612734576040519150601f19603f3d011682016040523d82523d6000602084013e612739565b606091505b509150915061274a87838387612757565b925050505b949350505050565b606083156127c35782516127bc576001600160a01b0385163b6127bc5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610891565b508161274f565b61274f83838151156127d85781518083602001fd5b8060405162461bcd60e51b815260040161089191906130ce565b8035610688816133ed565b60008083601f84011261280e578182fd5b50813567ffffffffffffffff811115612825578182fd5b602083019150836020808302850101111561283f57600080fd5b9250929050565b600082601f830112612856578081fd5b813567ffffffffffffffff80821115612871576128716133d7565b604051601f8301601f19908116603f01168101908282118183101715612899576128996133d7565b816040528381528660208588010111156128b1578485fd5b8360208701602083013792830160200193909352509392505050565b805169ffffffffffffffffffff8116811461068857600080fd5b6000602082840312156128f8578081fd5b8135612673816133ed565b600060208284031215612914578081fd5b8151612673816133ed565b60008060408385031215612931578081fd5b823561293c816133ed565b9150602083013561294c816133ed565b809150509250929050565b6000806000806080858703121561296c578182fd5b8435612977816133ed565b93506020850135612987816133ed565b92506040850135612997816133ed565b9396929550929360600135925050565b60008060008060008060c087890312156129bf578182fd5b86356129ca816133ed565b955060208701356129da816133ed565b945060408701356129ea816133ed565b9350606087013592506080870135915060a087013567ffffffffffffffff811115612a13578182fd5b612a1f89828a01612846565b9150509295509295509295565b600080600060608486031215612a40578283fd5b8335612a4b816133ed565b92506020840135612a5b816133ed565b929592945050506040919091013590565b600080600080600060a08688031215612a83578081fd5b8535612a8e816133ed565b94506020860135612a9e816133ed565b93506040860135925060608601359150608086013567ffffffffffffffff811115612ac7578182fd5b612ad388828901612846565b9150509295509295909350565b600080600080600080600060c0888a031215612afa578081fd5b8735612b05816133ed565b96506020880135612b15816133ed565b95506040880135945060608801359350608088013567ffffffffffffffff811115612b3e578182fd5b612b4a8a828b016127fd565b989b979a5095989497959660a090950135949350505050565b60008060008060008060008060006101008a8c031215612b81578283fd5b8935612b8c816133ed565b985060208a0135612b9c816133ed565b975060408a0135965060608a0135955060808a013567ffffffffffffffff80821115612bc6578485fd5b612bd28d838e016127fd565b909750955060a08c0135945060c08c0135935060e08c0135915080821115612bf8578283fd5b50612c058c828d01612846565b9150509295985092959850929598565b60008060408385031215612c27578182fd5b8235612c32816133ed565b946020939093013593505050565b600080600080600080600060c0888a031215612c5a578081fd5b8735612c65816133ed565b965060208801359550604088013567ffffffffffffffff811115612c87578182fd5b612c938a828b016127fd565b909650945050606088013592506080880135915060a0880135612cb5816133ed565b8091505092959891949750929550565b600080600080600060a08688031215612cdc578283fd5b8535612ce7816133ed565b945060208601359350604086013567ffffffffffffffff80821115612d0a578485fd5b612d1689838a01612846565b94506060880135915080821115612d2b578283fd5b612d3789838a01612846565b93506080880135915080821115612d4c578283fd5b50612ad388828901612846565b600080600080600060a08688031215612d70578283fd5b8535612d7b816133ed565b945060208601359350604086013592506060860135612d99816133ed565b91506080860135612da9816133ed565b809150509295509295909350565b60008060008060008060008060006101008a8c031215612dd5578283fd5b612dde8a6127f2565b985060208a0135975060408a0135965060608a013567ffffffffffffffff80821115612e08578485fd5b612e148d838e016127fd565b909850965060808c0135955060a08c0135915080821115612e33578485fd5b612e3f8d838e01612846565b945060c08c0135915080821115612e54578384fd5b612e608d838e01612846565b935060e08c0135915080821115612bf8578283fd5b60008060008060008060008060e0898b031215612e90578182fd5b8835612e9b816133ed565b97506020890135965060408901359550606089013567ffffffffffffffff811115612ec4578283fd5b612ed08b828c016127fd565b9096509450506080890135925060a0890135915060c0890135612ef2816133ed565b809150509295985092959890939650565b600060208284031215612f14578081fd5b81518015158114612673578182fd5b600060208284031215612f34578081fd5b5051919050565b600080600080600060a08688031215612f52578283fd5b612f5b866128cd565b9450602086015193506040860151925060608601519150612f7e608087016128cd565b90509295509295909350565b600060208284031215612f9b578081fd5b815160ff81168114612673578182fd5b60008151808452612fc3816020860160208601613395565b601f01601f19169290920160200192915050565b60008251612fe9818460208701613395565b9190910192915050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03868116825285166020820152604081018490526060810183905260a06080820181905260009061305190830184612fab565b979650505050505050565b6001600160a01b03929092168252602082015260400190565b600060018060a01b038716825285602083015260a0604083015261309c60a0830186612fab565b82810360608401526130ae8186612fab565b905082810360808401526130c28185612fab565b98975050505050505050565b6000602082526126736020830184612fab565b6020808252600990820152682130b2103a37b5b2b760b91b604082015260600190565b60208082526023908201527f4552524f523a2053414d4520544f4b454e20574954482053414d45204e4554576040820152624f524b60e81b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b868152602080820187905260a0604083018190528201859052600090869060c08401835b888110156131e45783356131c9816133ed565b6001600160a01b0316825292820192908201906001016131b6565b506001600160a01b0396909616606085015250505060800152949350505050565b60008261322057634e487b7160e01b81526012600452602481fd5b500490565b80825b60018086116132375750613262565b818704821115613249576132496133c1565b8086161561325657918102915b9490941c938002613228565b94509492505050565b600061267360001960ff85168460008261328757506001612673565b8161329457506000612673565b81600181146132aa57600281146132b4576132e1565b6001915050612673565b60ff8411156132c5576132c56133c1565b6001841b9150848211156132db576132db6133c1565b50612673565b5060208310610133831016604e8410600b8410161715613314575081810a8381111561330f5761330f6133c1565b612673565b6133218484846001613225565b808604821115613333576133336133c1565b02949350505050565b6000816000190483118215151615613356576133566133c1565b500290565b60008282101561336d5761336d6133c1565b500390565b600060ff821660ff84168082101561338c5761338c6133c1565b90039392505050565b60005b838110156133b0578181015183820152602001613398565b83811115611b805750506000910152565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461101957600080fdfea264697066735822122096063dd122c7f58c9c4b2090fd7f7b0b39209d110e4417f42bb29e8ffefe379f64736f6c63430008020033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/src/constants/constants.ts b/src/constants/constants.ts new file mode 100644 index 0000000..97069c2 --- /dev/null +++ b/src/constants/constants.ts @@ -0,0 +1,2 @@ +export const NAME = 'FiberRouter'; +export const VERSION = '000.001'; diff --git a/src/services/axios.service.ts b/src/services/axios.service.ts index b20cb9f..4462c7f 100644 --- a/src/services/axios.service.ts +++ b/src/services/axios.service.ts @@ -1,12 +1,8 @@ import axios from 'axios'; import dotenv from 'dotenv'; -import { Transaction } from '../interfaces'; dotenv.config(); -export const updateTransactionJobStatus = async ( - txHash: string, - body: Transaction, -) => { +export const updateTransactionJobStatus = async (txHash: string, body: any) => { const url = process.env.GATEWAY_BACKEND_URL; return axios.put( `${url}/api/v1/transactions/update/swap/and/withdraw/job/${txHash}`, diff --git a/src/services/web3.service.ts b/src/services/web3.service.ts index e3f248c..16fc3d2 100644 --- a/src/services/web3.service.ts +++ b/src/services/web3.service.ts @@ -1,5 +1,8 @@ import Web3 from 'web3'; import { TransactionReceipt, Transaction } from '../interfaces'; +import { abi as contractABI } from '../constants/FiberRouter.json'; +import { NAME, VERSION } from '../constants/constants'; +import { ethers } from 'ethers'; export const getTransactionReceipt = async ( txId: string, @@ -22,3 +25,129 @@ export const getTransactionByHash = async ( const web3 = new Web3(rpcURL); return web3.eth.getTransaction(txHash); }; + +export const signedTransaction = async ( + rpcURL: string, + tx: any, +): Promise => { + try { + const web3 = new Web3(rpcURL); + const inter = new ethers.utils.Interface(contractABI); + const decodedInput = inter.parseTransaction({ + data: tx.input, + value: tx.value, + }); + const txData = { + transactionHash: tx.hash, + from: tx.from, + token: decodedInput.args[0], + amount: decodedInput.args[1].toString(), + contractAddress: tx.to, + chainId: web3.utils.hexToNumberString(tx.chainId.toString()), + targetChainId: decodedInput.args[2].toString(), + targetToken: decodedInput.args[3], + targetAddress: decodedInput.args[4], + signatures: [], + salt: '', + }; + + txData.salt = Web3.utils.keccak256( + txData.transactionHash.toLocaleLowerCase(), + ); + const payBySig = createSignedPayment( + txData.chainId, + txData.from, + txData.amount, + txData.token, + txData.contractAddress, + txData.salt, + web3, + ); + return { ...txData, signatures: payBySig.signatures, hash: payBySig.hash }; + } catch (error) { + console.error('Error occured while decoding transaction', error); + } +}; + +const createSignedPayment = ( + chainId: string, + address: string, + amount: string, + token: string, + contractAddress: string, + salt: string, + web3: Web3, +) => { + const payBySig = produceSignatureWithdrawHash( + web3, + chainId, + contractAddress, + token, + address, + amount, + salt, + ); + const privateKey = process.env.PRIVATE_KEY as string; + const sign = web3.eth.accounts.sign(payBySig.hash, privateKey); + payBySig.signatures = [{ signature: sign.signature } as any]; + return payBySig; +}; +const produceSignatureWithdrawHash = ( + web3: Web3, + chainId: string, + contractAddress: string, + token: string, + payee: string, + amount: string, + swapTxId: string, +): any => { + const methodHash = Web3.utils.keccak256( + Web3.utils.utf8ToHex( + 'WithdrawSigned(address token,address payee,uint256 amount,bytes32 salt)', + ), + ); + const params = ['bytes32', 'address', 'address', 'uint256', 'bytes32']; + const structure = web3.eth.abi.encodeParameters(params, [ + methodHash, + token, + payee, + amount, + swapTxId, + ]); + const structureHash = Web3.utils.keccak256(structure); + const ds = domainSeparator(web3, chainId, contractAddress); + const hash = Web3.utils.soliditySha3('\x19\x01', ds, structureHash); + return { + contractName: NAME, + contractVersion: VERSION, + contractAddress: contractAddress, + amount, + payee, + signatures: [], + token, + swapTxId, + sourceChainId: 0, + toToken: '', + hash, + }; +}; + +const domainSeparator = ( + web3: Web3, + chainId: string, + contractAddress: string, +) => { + const hashedName = Web3.utils.keccak256(Web3.utils.utf8ToHex(NAME)); + const hashedVersion = Web3.utils.keccak256(Web3.utils.utf8ToHex(VERSION)); + const typeHash = Web3.utils.keccak256( + Web3.utils.utf8ToHex( + 'EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)', + ), + ); + return Web3.utils.keccak256( + web3.eth.abi.encodeParameters( + ['bytes32', 'bytes32', 'bytes32', 'uint256', 'address'], + [typeHash, hashedName, hashedVersion, chainId, contractAddress], + ), + ); +}; diff --git a/src/worker.ts b/src/worker.ts index cf61f4e..8435e15 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -13,12 +13,17 @@ const worker = new Worker( }, ); worker.on('completed', async job => { - console.info(`${job.id} has completed!`); - const tx = await web3Service.getTransactionByHash( - job.data.txId, - job.data.rpcURL, - ); - axiosService.updateTransactionJobStatus(tx.hash, tx); + try { + console.info(`${job.id} has completed!`); + const tx = await web3Service.getTransactionByHash( + job.data.txId, + job.data.rpcURL, + ); + const signedData = await web3Service.signedTransaction(job.data.rpcURL, tx); + axiosService.updateTransactionJobStatus(tx.hash, { signedData, tx }); + } catch (error) { + console.error('error occured', error); + } }); worker.on('failed', async (job: any, err) => { From bbab91b11a0fcd31a4bef3986673f841e3ccd8f8 Mon Sep 17 00:00:00 2001 From: Abdul Ahad Date: Mon, 27 Feb 2023 15:49:58 +0500 Subject: [PATCH 06/36] source chainId fixed --- src/services/web3.service.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/services/web3.service.ts b/src/services/web3.service.ts index 16fc3d2..d70eb07 100644 --- a/src/services/web3.service.ts +++ b/src/services/web3.service.ts @@ -37,13 +37,14 @@ export const signedTransaction = async ( data: tx.input, value: tx.value, }); + const sourceChainId = await web3.eth.getChainId(); const txData = { transactionHash: tx.hash, from: tx.from, token: decodedInput.args[0], amount: decodedInput.args[1].toString(), contractAddress: tx.to, - chainId: web3.utils.hexToNumberString(tx.chainId.toString()), + chainId: web3.utils.hexToNumberString(sourceChainId), targetChainId: decodedInput.args[2].toString(), targetToken: decodedInput.args[3], targetAddress: decodedInput.args[4], From c8089863dffe23ed27216a28ec642b8cfb90d1e2 Mon Sep 17 00:00:00 2001 From: Abdul Ahad Date: Tue, 28 Feb 2023 14:25:18 +0500 Subject: [PATCH 07/36] ci/cd test --- src/controllers/job.controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/job.controller.ts b/src/controllers/job.controller.ts index a843f11..d771ad2 100644 --- a/src/controllers/job.controller.ts +++ b/src/controllers/job.controller.ts @@ -4,7 +4,7 @@ import { jobService } from '../services'; export const createJob = async (req: Request, res: Response): Promise => { try { const job = await jobService.addJobs(req.body); - res.send({jobId: job.id}); + res.send({ jobId: job.id, job }); } catch (err) { console.error(err); } From 0b022f040318ead0d46cb2bf7aaa507cc1149646 Mon Sep 17 00:00:00 2001 From: Zikriya Date: Tue, 28 Feb 2023 19:08:18 +0500 Subject: [PATCH 08/36] createJobBySwapHash api response updated --- src/worker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/worker.ts b/src/worker.ts index d98b269..c0b824a 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -20,7 +20,7 @@ worker.on('completed', async job => { job.data.rpcURL, ); const signedData = await web3Service.signedTransaction(job.data.rpcURL, tx); - axiosService.updateTransactionJobStatus(tx.hash, { signedData, tx }); + axiosService.updateTransactionJobStatus(tx.hash, { signedData, transaction: tx, transactionReceipt: job?.returnvalue },); } catch (error) { console.error('error occured', error); } From 02abf55c733ba85a6321c09ec4fe4478b967b769 Mon Sep 17 00:00:00 2001 From: Abdul Ahad Date: Wed, 1 Mar 2023 16:42:44 +0500 Subject: [PATCH 09/36] updated code for event decode --- src/worker.ts | 55 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/src/worker.ts b/src/worker.ts index d98b269..15a5040 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -1,6 +1,11 @@ import { Worker } from 'bullmq'; import { web3Service, axiosService } from './services'; - +import Web3 from 'web3'; +import { abi as contractABI } from './constants/FiberRouter.json'; +const swapEventHash = Web3.utils.sha3( + 'Swap(address,address,uint256,uint256,uint256,address,address)', +); +console.log(swapEventHash, 'swapEventHash'); const worker = new Worker( process.env.QUEUE as string, async job => @@ -15,12 +20,14 @@ const worker = new Worker( worker.on('completed', async job => { try { console.info(`${job.id} has completed!`); - const tx = await web3Service.getTransactionByHash( - job.data.txId, - job.data.rpcURL, - ); - const signedData = await web3Service.signedTransaction(job.data.rpcURL, tx); - axiosService.updateTransactionJobStatus(tx.hash, { signedData, tx }); + + getLogsFromTransactionReceipt(job); + // const tx = await web3Service.getTransactionByHash( + // job.data.txId, + // job.data.rpcURL, + // ); + // const signedData = await web3Service.signedTransaction(job.data.rpcURL, tx); + // axiosService.updateTransactionJobStatus(tx.hash, { signedData, tx }); } catch (error) { console.error('error occured', error); } @@ -38,4 +45,38 @@ worker.on('failed', async (job: any, err) => { }); }); +const getLogsFromTransactionReceipt = (job: any) => { + let topics: any[][] = []; + if (job?.returnvalue?.logs?.length) { + for (const log of job.returnvalue.logs) { + topics = [...topics, getAllTopics(log)]; + } + } + if (topics?.length) { + for (const topic of topics) { + const topicIndex = findSwapEvent(topic); + if (topicIndex !== undefined && topicIndex >= 0) { + // console.log(topic, topicIndex); + } + } + } + console.log(topics); +}; + +const getAllTopics = (log: any) => { + if (log?.topics?.length) { + return log.topics; + } else { + return []; + } +}; + +const findSwapEvent = (topics: any[]) => { + if (topics?.length) { + return topics.findIndex(topic => topic === swapEventHash); + } else { + return undefined; + } +}; + export default worker; From e22a0d6df15eae86c845b34d611db22100c3619f Mon Sep 17 00:00:00 2001 From: Abdul Ahad Date: Thu, 2 Mar 2023 12:08:39 +0500 Subject: [PATCH 10/36] event decoded using web3 js --- src/worker.ts | 48 ++++++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/src/worker.ts b/src/worker.ts index 15a5040..ad12689 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -5,7 +5,10 @@ import { abi as contractABI } from './constants/FiberRouter.json'; const swapEventHash = Web3.utils.sha3( 'Swap(address,address,uint256,uint256,uint256,address,address)', ); -console.log(swapEventHash, 'swapEventHash'); +const swapEventInputs = contractABI.find( + abi => abi.name === 'Swap' && abi.type === 'event', +)?.inputs; + const worker = new Worker( process.env.QUEUE as string, async job => @@ -46,29 +49,38 @@ worker.on('failed', async (job: any, err) => { }); const getLogsFromTransactionReceipt = (job: any) => { - let topics: any[][] = []; + let logDataAndTopic = undefined; + if (job?.returnvalue?.logs?.length) { for (const log of job.returnvalue.logs) { - topics = [...topics, getAllTopics(log)]; - } - } - if (topics?.length) { - for (const topic of topics) { - const topicIndex = findSwapEvent(topic); - if (topicIndex !== undefined && topicIndex >= 0) { - // console.log(topic, topicIndex); + if (log?.topics?.length) { + const topicIndex = findSwapEvent(log.topics); + if (topicIndex !== undefined && topicIndex >= 0) { + logDataAndTopic = { + data: log.data, + topics: log.topics, + }; + break; + } } } - } - console.log(topics); -}; + if (logDataAndTopic?.data && logDataAndTopic.topics) { + const web3 = new Web3(job.data.rpcURL); -const getAllTopics = (log: any) => { - if (log?.topics?.length) { - return log.topics; - } else { - return []; + console.log(logDataAndTopic); + console.log(swapEventInputs); + + const decodedLog = web3.eth.abi.decodeLog( + swapEventInputs as any, + logDataAndTopic.data, + logDataAndTopic.topics.slice(1), + ); + + console.log(decodedLog); + } } + + // console.log(topics); }; const findSwapEvent = (topics: any[]) => { From 4f3c322b6475ac7afdaec1b1c3e9d02164ba031b Mon Sep 17 00:00:00 2001 From: Abdul Ahad Date: Thu, 2 Mar 2023 13:35:37 +0500 Subject: [PATCH 11/36] signature with event logs --- package.json | 1 - src/controllers/job.controller.ts | 2 +- src/services/web3.service.ts | 76 +++++++++++++++++++++++-------- src/worker.ts | 66 +++------------------------ 4 files changed, 65 insertions(+), 80 deletions(-) diff --git a/package.json b/package.json index df64735..692c760 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,6 @@ "axios": "^1.2.6", "bullmq": "^3.5.11", "dotenv": "^16.0.3", - "ethers": "^5.6.3", "express": "^4.17.2", "web3": "^1.8.1" } diff --git a/src/controllers/job.controller.ts b/src/controllers/job.controller.ts index d771ad2..2553f8b 100644 --- a/src/controllers/job.controller.ts +++ b/src/controllers/job.controller.ts @@ -4,7 +4,7 @@ import { jobService } from '../services'; export const createJob = async (req: Request, res: Response): Promise => { try { const job = await jobService.addJobs(req.body); - res.send({ jobId: job.id, job }); + res.send({ jobId: job.id }); } catch (err) { console.error(err); } diff --git a/src/services/web3.service.ts b/src/services/web3.service.ts index d70eb07..0e76e22 100644 --- a/src/services/web3.service.ts +++ b/src/services/web3.service.ts @@ -2,7 +2,6 @@ import Web3 from 'web3'; import { TransactionReceipt, Transaction } from '../interfaces'; import { abi as contractABI } from '../constants/FiberRouter.json'; import { NAME, VERSION } from '../constants/constants'; -import { ethers } from 'ethers'; export const getTransactionReceipt = async ( txId: string, @@ -27,27 +26,21 @@ export const getTransactionByHash = async ( }; export const signedTransaction = async ( - rpcURL: string, - tx: any, + job: any, + decodedData: any, ): Promise => { try { - const web3 = new Web3(rpcURL); - const inter = new ethers.utils.Interface(contractABI); - const decodedInput = inter.parseTransaction({ - data: tx.input, - value: tx.value, - }); - const sourceChainId = await web3.eth.getChainId(); + const web3 = new Web3(job.data.rpcURL); const txData = { - transactionHash: tx.hash, - from: tx.from, - token: decodedInput.args[0], - amount: decodedInput.args[1].toString(), - contractAddress: tx.to, - chainId: web3.utils.hexToNumberString(sourceChainId), - targetChainId: decodedInput.args[2].toString(), - targetToken: decodedInput.args[3], - targetAddress: decodedInput.args[4], + transactionHash: job.returnvalue.transactionHash, + from: decodedData.sourceAddress, + token: decodedData.sourceToken, + amount: decodedData.sourceAmount, + contractAddress: job.returnvalue.to, + chainId: decodedData.sourceChainId, + targetChainId: decodedData.targetChainId, + targetToken: decodedData.targetToken, + targetAddress: decodedData.targetAddress, signatures: [], salt: '', }; @@ -152,3 +145,48 @@ const domainSeparator = ( ), ); }; + +export const getLogsFromTransactionReceipt = (job: any) => { + let logDataAndTopic = undefined; + + if (job?.returnvalue?.logs?.length) { + for (const log of job.returnvalue.logs) { + if (log?.topics?.length) { + const topicIndex = findSwapEvent(log.topics); + if (topicIndex !== undefined && topicIndex >= 0) { + logDataAndTopic = { + data: log.data, + topics: log.topics, + }; + break; + } + } + } + + const swapEventInputs = contractABI.find( + abi => abi.name === 'Swap' && abi.type === 'event', + )?.inputs; + if (logDataAndTopic?.data && logDataAndTopic.topics) { + const web3 = new Web3(job.data.rpcURL); + + const decodedLog = web3.eth.abi.decodeLog( + swapEventInputs as any, + logDataAndTopic.data, + logDataAndTopic.topics.slice(1), + ); + + return decodedLog; + } + } +}; + +const findSwapEvent = (topics: any[]) => { + const swapEventHash = Web3.utils.sha3( + 'Swap(address,address,uint256,uint256,uint256,address,address)', + ); + if (topics?.length) { + return topics.findIndex(topic => topic === swapEventHash); + } else { + return undefined; + } +}; diff --git a/src/worker.ts b/src/worker.ts index ad12689..7e0d5ad 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -1,13 +1,5 @@ import { Worker } from 'bullmq'; import { web3Service, axiosService } from './services'; -import Web3 from 'web3'; -import { abi as contractABI } from './constants/FiberRouter.json'; -const swapEventHash = Web3.utils.sha3( - 'Swap(address,address,uint256,uint256,uint256,address,address)', -); -const swapEventInputs = contractABI.find( - abi => abi.name === 'Swap' && abi.type === 'event', -)?.inputs; const worker = new Worker( process.env.QUEUE as string, @@ -23,14 +15,13 @@ const worker = new Worker( worker.on('completed', async job => { try { console.info(`${job.id} has completed!`); - - getLogsFromTransactionReceipt(job); - // const tx = await web3Service.getTransactionByHash( - // job.data.txId, - // job.data.rpcURL, - // ); - // const signedData = await web3Service.signedTransaction(job.data.rpcURL, tx); - // axiosService.updateTransactionJobStatus(tx.hash, { signedData, tx }); + const decodedData = web3Service.getLogsFromTransactionReceipt(job); + const tx = await web3Service.getTransactionByHash( + job.data.txId, + job.data.rpcURL, + ); + const signedData = await web3Service.signedTransaction(job, decodedData); + axiosService.updateTransactionJobStatus(tx.hash, { signedData, tx }); } catch (error) { console.error('error occured', error); } @@ -48,47 +39,4 @@ worker.on('failed', async (job: any, err) => { }); }); -const getLogsFromTransactionReceipt = (job: any) => { - let logDataAndTopic = undefined; - - if (job?.returnvalue?.logs?.length) { - for (const log of job.returnvalue.logs) { - if (log?.topics?.length) { - const topicIndex = findSwapEvent(log.topics); - if (topicIndex !== undefined && topicIndex >= 0) { - logDataAndTopic = { - data: log.data, - topics: log.topics, - }; - break; - } - } - } - if (logDataAndTopic?.data && logDataAndTopic.topics) { - const web3 = new Web3(job.data.rpcURL); - - console.log(logDataAndTopic); - console.log(swapEventInputs); - - const decodedLog = web3.eth.abi.decodeLog( - swapEventInputs as any, - logDataAndTopic.data, - logDataAndTopic.topics.slice(1), - ); - - console.log(decodedLog); - } - } - - // console.log(topics); -}; - -const findSwapEvent = (topics: any[]) => { - if (topics?.length) { - return topics.findIndex(topic => topic === swapEventHash); - } else { - return undefined; - } -}; - export default worker; From eca6340a3b02462413e41b6216be523a22db182b Mon Sep 17 00:00:00 2001 From: Abdul Ahad Date: Thu, 2 Mar 2023 14:15:33 +0500 Subject: [PATCH 12/36] update the response data --- src/worker.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/worker.ts b/src/worker.ts index 7e0d5ad..5a73e29 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -21,7 +21,11 @@ worker.on('completed', async job => { job.data.rpcURL, ); const signedData = await web3Service.signedTransaction(job, decodedData); - axiosService.updateTransactionJobStatus(tx.hash, { signedData, tx }); + axiosService.updateTransactionJobStatus(tx.hash, { + signedData, + transaction: tx, + transactionReceipt: job?.returnvalue, + }); } catch (error) { console.error('error occured', error); } From 5f8a4e7c3b2f90ca638bdbd7e64b8133c9457466 Mon Sep 17 00:00:00 2001 From: Zikriya Date: Thu, 9 Mar 2023 14:00:53 +0500 Subject: [PATCH 13/36] Remove ignored files cache --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 297d2d8..499cf08 100644 --- a/.gitignore +++ b/.gitignore @@ -22,4 +22,7 @@ yarn-error.log !.env*.example # Code coverage -coverage \ No newline at end of file +coverage + +# package lock +package-lock.json \ No newline at end of file From ca0d6eb6200a276b7d07aeb9cd411ca6ccdbccf2 Mon Sep 17 00:00:00 2001 From: Zikriya Date: Thu, 9 Mar 2023 15:08:26 +0500 Subject: [PATCH 14/36] ethereumjs-util added to create the signature. Also contractAddress param have changed to static, only for BSC --- package.json | 1 + src/constants/constants.ts | 5 +++-- src/services/web3.service.ts | 25 +++++++++++++++++++++---- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 692c760..1b5094f 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "axios": "^1.2.6", "bullmq": "^3.5.11", "dotenv": "^16.0.3", + "ethereumjs-util": "^7.1.5", "express": "^4.17.2", "web3": "^1.8.1" } diff --git a/src/constants/constants.ts b/src/constants/constants.ts index 97069c2..566ec00 100644 --- a/src/constants/constants.ts +++ b/src/constants/constants.ts @@ -1,2 +1,3 @@ -export const NAME = 'FiberRouter'; -export const VERSION = '000.001'; +export const NAME = 'FERRUM_TOKEN_BRIDGE_POOL'; +export const VERSION = '000.004'; +export const CONTRACT_ADDRESS = "0x9aFe354fb34a6303a9b9C89fF43A509A5320ba2D"; diff --git a/src/services/web3.service.ts b/src/services/web3.service.ts index 0e76e22..3bb1e62 100644 --- a/src/services/web3.service.ts +++ b/src/services/web3.service.ts @@ -1,7 +1,8 @@ import Web3 from 'web3'; import { TransactionReceipt, Transaction } from '../interfaces'; import { abi as contractABI } from '../constants/FiberRouter.json'; -import { NAME, VERSION } from '../constants/constants'; +import { NAME, VERSION, CONTRACT_ADDRESS } from '../constants/constants'; +import { ecsign, toRpcSig } from "ethereumjs-util"; export const getTransactionReceipt = async ( txId: string, @@ -36,7 +37,7 @@ export const signedTransaction = async ( from: decodedData.sourceAddress, token: decodedData.sourceToken, amount: decodedData.sourceAmount, - contractAddress: job.returnvalue.to, + contractAddress: CONTRACT_ADDRESS, chainId: decodedData.sourceChainId, targetChainId: decodedData.targetChainId, targetToken: decodedData.targetToken, @@ -82,10 +83,15 @@ const createSignedPayment = ( salt, ); const privateKey = process.env.PRIVATE_KEY as string; - const sign = web3.eth.accounts.sign(payBySig.hash, privateKey); - payBySig.signatures = [{ signature: sign.signature } as any]; + const ecSign = ecsign( + Buffer.from(payBySig.hash.replace("0x", ""), "hex"), + Buffer.from(privateKey.replace("0x", ""), "hex") + ); + const sign = fixSig(toRpcSig(ecSign.v, ecSign.r, ecSign.s)); + payBySig.signatures = [sign]; return payBySig; }; + const produceSignatureWithdrawHash = ( web3: Web3, chainId: string, @@ -190,3 +196,14 @@ const findSwapEvent = (topics: any[]) => { return undefined; } }; + +const fixSig = (sig:any) => { + const rs = sig.substring(0, sig.length - 2); + let v = sig.substring(sig.length - 2); + if (v === '00' || v === '37' || v === '25') { + v = '1b' + } else if (v === '01' || v === '38' || v === '26') { + v = '1c' + } + return rs + v; +} From 79571201107c6626dde3eb3b269b0985a4ea0e92 Mon Sep 17 00:00:00 2001 From: Zikriya Date: Tue, 14 Mar 2023 18:13:56 +0500 Subject: [PATCH 15/36] getHealth api added to check health at loadbalancer. Also one bug fixed at web3.service, await added at getTransactionReceipt --- src/controllers/job.controller.ts | 8 ++++++++ src/routes/job.route.ts | 1 + src/services/web3.service.ts | 5 +++-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/controllers/job.controller.ts b/src/controllers/job.controller.ts index 2553f8b..c7611d6 100644 --- a/src/controllers/job.controller.ts +++ b/src/controllers/job.controller.ts @@ -18,3 +18,11 @@ export const getJob = async (req: Request, res: Response): Promise => { console.error(err); } }; + +export const getHealth = async (req: Request, res: Response): Promise => { + try { + res.send(''); + } catch (err) { + console.error(err); + } +}; diff --git a/src/routes/job.route.ts b/src/routes/job.route.ts index e13b11d..1f444f0 100644 --- a/src/routes/job.route.ts +++ b/src/routes/job.route.ts @@ -5,4 +5,5 @@ const router = Router(); router.route('/').post(jobController.createJob); router.route('/:id').get(jobController.getJob); +router.route('/health').get(jobController.getHealth); export default router; diff --git a/src/services/web3.service.ts b/src/services/web3.service.ts index 3bb1e62..c51abfc 100644 --- a/src/services/web3.service.ts +++ b/src/services/web3.service.ts @@ -12,8 +12,9 @@ export const getTransactionReceipt = async ( const transaction: TransactionReceipt = await web3.eth.getTransactionReceipt( txId, ); - if (transaction === null || transaction.status === null) { - getTransactionReceipt(txId, rpcURL); + + if (!transaction || transaction === null || transaction.status === null) { + await getTransactionReceipt(txId, rpcURL); } return transaction; }; From ac8d7ed2c1cdd7b8c4de8dc9eb9801fd6ab3c3bf Mon Sep 17 00:00:00 2001 From: Zikriya Date: Tue, 14 Mar 2023 18:53:36 +0500 Subject: [PATCH 16/36] getTransactionReceipt called at on complete to get the latest reciept --- src/worker.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/worker.ts b/src/worker.ts index 5a73e29..66aad45 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -15,6 +15,10 @@ const worker = new Worker( worker.on('completed', async job => { try { console.info(`${job.id} has completed!`); + if(job && !job.returnvalue){ + console.info(`Get latest receipt`); + job.returnvalue = await web3Service.getTransactionReceipt(job.data.txId, job.data.rpcURL); + } const decodedData = web3Service.getLogsFromTransactionReceipt(job); const tx = await web3Service.getTransactionByHash( job.data.txId, From e774f0b46b9020e2f0700e18e9065d2df25eca96 Mon Sep 17 00:00:00 2001 From: sherazriaz-git Date: Wed, 15 Mar 2023 10:24:23 +0500 Subject: [PATCH 17/36] enable CI/CD --- .github/workflow/deploy_dev.yaml | 42 ++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 .github/workflow/deploy_dev.yaml diff --git a/.github/workflow/deploy_dev.yaml b/.github/workflow/deploy_dev.yaml new file mode 100644 index 0000000..a71299b --- /dev/null +++ b/.github/workflow/deploy_dev.yaml @@ -0,0 +1,42 @@ + +name: Deploy to ECS + +on: + + push: + branches: [ develop ] + +jobs: + + build: + + name: Build Image + runs-on: ubuntu-latest + + + steps: + + - name: Check out code + uses: actions/checkout@v2 + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: us-east-2 + + - name: Login to Amazon ECR + id: login-ecr + uses: aws-actions/amazon-ecr-login@v1 + + - name: Build, tag, and push image to Amazon ECR + env: + ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} + ECR_REPOSITORY: ferrum-dev-multiswap + IMAGE_TAG: latest + run: | + docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$GITHUB_SHA . + docker $ECR_REGISTRY/$ECR_REPOSITORY:$GITHUB_SHA $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG + docker push $ECR_REGISTRY/$ECR_REPOSITORY:$GITHUB_SHA + docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG \ No newline at end of file From 728216c715f6ebdec1b7897901180c7c3bb503e3 Mon Sep 17 00:00:00 2001 From: sherazriaz-git Date: Wed, 15 Mar 2023 11:03:55 +0500 Subject: [PATCH 18/36] ECS CI/CD --- .github/workflow/deploy_dev.yaml | 64 ++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 19 deletions(-) diff --git a/.github/workflow/deploy_dev.yaml b/.github/workflow/deploy_dev.yaml index a71299b..0d1f856 100644 --- a/.github/workflow/deploy_dev.yaml +++ b/.github/workflow/deploy_dev.yaml @@ -1,42 +1,68 @@ - -name: Deploy to ECS +name: Deploy to Amazon ECS on: - push: - branches: [ develop ] + branches: [ "develop" ] + +env: + AWS_REGION: us-east-2 # set this to your preferred AWS region, e.g. us-west-1 + ECR_REPOSITORY: ferrum-dev-multiswap # set this to your Amazon ECR repository name + ECS_SERVICE: multiswap-node # set this to your Amazon ECS service name + ECS_CLUSTER: ferrum-dev-cluster # set this to your Amazon ECS cluster name + ECS_TASK_DEFINITION: multiswap-node # set this to the path to your Amazon ECS task definition + # file, e.g. .aws/task-definition.json + CONTAINER_NAME: multiswap-node # set this to the name of the container in the + # containerDefinitions section of your task definition + +permissions: + contents: read jobs: - - build: - - name: Build Image + deploy: + name: Deploy runs-on: ubuntu-latest + environment: production - steps: + - name: Checkout + uses: actions/checkout@v3 - - name: Check out code - uses: actions/checkout@v2 - - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v1 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - aws-region: us-east-2 + aws-region: ${{ env.AWS_REGION }} - name: Login to Amazon ECR id: login-ecr uses: aws-actions/amazon-ecr-login@v1 - name: Build, tag, and push image to Amazon ECR + id: build-image env: ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} - ECR_REPOSITORY: ferrum-dev-multiswap - IMAGE_TAG: latest + IMAGE_TAG: ${{ github.sha }} run: | - docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$GITHUB_SHA . - docker $ECR_REGISTRY/$ECR_REPOSITORY:$GITHUB_SHA $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG - docker push $ECR_REGISTRY/$ECR_REPOSITORY:$GITHUB_SHA - docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG \ No newline at end of file + # Build a docker container and + # push it to ECR so that it can + # be deployed to ECS. + docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG . + docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG + echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT + + - name: Fill in the new image ID in the Amazon ECS task definition + id: task-def + uses: aws-actions/amazon-ecs-render-task-definition@v1 + with: + task-definition: ${{ env.ECS_TASK_DEFINITION }} + container-name: ${{ env.CONTAINER_NAME }} + image: ${{ steps.build-image.outputs.image }} + + - name: Deploy Amazon ECS task definition + uses: aws-actions/amazon-ecs-deploy-task-definition@v1 + with: + task-definition: ${{ steps.task-def.outputs.task-definition }} + service: ${{ env.ECS_SERVICE }} + cluster: ${{ env.ECS_CLUSTER }} + wait-for-service-stability: true \ No newline at end of file From b3725b9035b544b5dbf3f649beea3f847765cf40 Mon Sep 17 00:00:00 2001 From: sherazriaz-git Date: Wed, 15 Mar 2023 11:06:20 +0500 Subject: [PATCH 19/36] change branch syntax --- .github/workflow/deploy_dev.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflow/deploy_dev.yaml b/.github/workflow/deploy_dev.yaml index 0d1f856..ec2ef0b 100644 --- a/.github/workflow/deploy_dev.yaml +++ b/.github/workflow/deploy_dev.yaml @@ -2,7 +2,8 @@ name: Deploy to Amazon ECS on: push: - branches: [ "develop" ] + branches: + - develop env: AWS_REGION: us-east-2 # set this to your preferred AWS region, e.g. us-west-1 From 6e01eba8b03717df4587d82ec6ee86cd70d44c6d Mon Sep 17 00:00:00 2001 From: sherazriaz-git Date: Wed, 15 Mar 2023 11:07:43 +0500 Subject: [PATCH 20/36] change workflow folder name --- .github/{workflow => workflows}/deploy_dev.yaml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/{workflow => workflows}/deploy_dev.yaml (100%) diff --git a/.github/workflow/deploy_dev.yaml b/.github/workflows/deploy_dev.yaml similarity index 100% rename from .github/workflow/deploy_dev.yaml rename to .github/workflows/deploy_dev.yaml From c31406345c4325e3f3c249602b72ccd07eb5ab89 Mon Sep 17 00:00:00 2001 From: sherazriaz-git Date: Wed, 15 Mar 2023 11:17:54 +0500 Subject: [PATCH 21/36] update ecs service --- .github/workflows/deploy_dev.yaml | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/.github/workflows/deploy_dev.yaml b/.github/workflows/deploy_dev.yaml index ec2ef0b..8af5d07 100644 --- a/.github/workflows/deploy_dev.yaml +++ b/.github/workflows/deploy_dev.yaml @@ -52,18 +52,11 @@ jobs: docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT - - name: Fill in the new image ID in the Amazon ECS task definition - id: task-def - uses: aws-actions/amazon-ecs-render-task-definition@v1 - with: - task-definition: ${{ env.ECS_TASK_DEFINITION }} - container-name: ${{ env.CONTAINER_NAME }} - image: ${{ steps.build-image.outputs.image }} - - name: Deploy Amazon ECS task definition + - name: Update Amazon ECS service uses: aws-actions/amazon-ecs-deploy-task-definition@v1 with: - task-definition: ${{ steps.task-def.outputs.task-definition }} service: ${{ env.ECS_SERVICE }} cluster: ${{ env.ECS_CLUSTER }} + container-image-name-updates: container=my-conatiner,tag=${{ github.sha }} wait-for-service-stability: true \ No newline at end of file From 22603ac070163006fb5418cde11bc632d4925bef Mon Sep 17 00:00:00 2001 From: sherazriaz-git Date: Wed, 15 Mar 2023 11:20:46 +0500 Subject: [PATCH 22/36] test --- .github/workflows/deploy_dev.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy_dev.yaml b/.github/workflows/deploy_dev.yaml index 8af5d07..c41079e 100644 --- a/.github/workflows/deploy_dev.yaml +++ b/.github/workflows/deploy_dev.yaml @@ -58,5 +58,5 @@ jobs: with: service: ${{ env.ECS_SERVICE }} cluster: ${{ env.ECS_CLUSTER }} - container-image-name-updates: container=my-conatiner,tag=${{ github.sha }} + container-image-name-updates: container=${{ env.CONTAINER_NAME}},tag=${{ github.sha }} wait-for-service-stability: true \ No newline at end of file From 464795284cb4f15a3f1ba5c8a18f7f8daa6bf450 Mon Sep 17 00:00:00 2001 From: sherazriaz-git Date: Wed, 15 Mar 2023 11:25:24 +0500 Subject: [PATCH 23/36] update variable --- .github/workflows/deploy_dev.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy_dev.yaml b/.github/workflows/deploy_dev.yaml index c41079e..9751c6e 100644 --- a/.github/workflows/deploy_dev.yaml +++ b/.github/workflows/deploy_dev.yaml @@ -58,5 +58,5 @@ jobs: with: service: ${{ env.ECS_SERVICE }} cluster: ${{ env.ECS_CLUSTER }} - container-image-name-updates: container=${{ env.CONTAINER_NAME}},tag=${{ github.sha }} + task-definition: container=${{ env.CONTAINER_NAME}},tag=${{ github.sha }} wait-for-service-stability: true \ No newline at end of file From ed9c24ba96dfa3c22770d66f8c6fe2c6067f6c45 Mon Sep 17 00:00:00 2001 From: sherazriaz-git Date: Wed, 15 Mar 2023 11:29:57 +0500 Subject: [PATCH 24/36] push images to ECR --- .github/workflows/deploy_dev.yaml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/deploy_dev.yaml b/.github/workflows/deploy_dev.yaml index 9751c6e..810b82e 100644 --- a/.github/workflows/deploy_dev.yaml +++ b/.github/workflows/deploy_dev.yaml @@ -53,10 +53,10 @@ jobs: echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT - - name: Update Amazon ECS service - uses: aws-actions/amazon-ecs-deploy-task-definition@v1 - with: - service: ${{ env.ECS_SERVICE }} - cluster: ${{ env.ECS_CLUSTER }} - task-definition: container=${{ env.CONTAINER_NAME}},tag=${{ github.sha }} - wait-for-service-stability: true \ No newline at end of file + # - name: Update Amazon ECS service + # uses: aws-actions/amazon-ecs-deploy-task-definition@v1 + # with: + # service: ${{ env.ECS_SERVICE }} + # cluster: ${{ env.ECS_CLUSTER }} + # task-definition: container=${{ env.CONTAINER_NAME}},tag=${{ github.sha }} + # wait-for-service-stability: true \ No newline at end of file From 021c215e2034eb4670824e9d332c7aa45a988857 Mon Sep 17 00:00:00 2001 From: Sheraz Riaz Date: Fri, 17 Mar 2023 10:00:18 +0500 Subject: [PATCH 25/36] push images with latest label --- .github/workflows/deploy_dev.yaml | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy_dev.yaml b/.github/workflows/deploy_dev.yaml index 810b82e..5590647 100644 --- a/.github/workflows/deploy_dev.yaml +++ b/.github/workflows/deploy_dev.yaml @@ -49,8 +49,26 @@ jobs: # push it to ECR so that it can # be deployed to ECS. docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG . + docker tag $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG $ECR_REGISTRY/$ECR_REPOSITORY:latest docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG - echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT + docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest + + + # - name: Fill in the new image ID in the Amazon ECS task definition + # id: task-def + # uses: aws-actions/amazon-ecs-render-task-definition@v1 + # with: + # task-definition: ${{ env.ECS_TASK_DEFINITION }} + # container-name: ${{ env.CONTAINER_NAME }} + # image: ${{ steps.build-image.outputs.image }} + + # - name: Deploy Amazon ECS task definition + # uses: aws-actions/amazon-ecs-deploy-task-definition@v1 + # with: + # task-definition: ${{ steps.task-def.outputs.task-definition }} + # service: ${{ env.ECS_SERVICE }} + # cluster: ${{ env.ECS_CLUSTER }} + # wait-for-service-stability: true # - name: Update Amazon ECS service From 17a7f2e77734bd7ac94a6c07ee067532a1a4be82 Mon Sep 17 00:00:00 2001 From: Sheraz Riaz Date: Fri, 17 Mar 2023 10:21:11 +0500 Subject: [PATCH 26/36] ecs deploy --- .github/workflows/deploy_dev.yaml | 40 +++++++++++-------------------- 1 file changed, 14 insertions(+), 26 deletions(-) diff --git a/.github/workflows/deploy_dev.yaml b/.github/workflows/deploy_dev.yaml index 5590647..87f557a 100644 --- a/.github/workflows/deploy_dev.yaml +++ b/.github/workflows/deploy_dev.yaml @@ -19,10 +19,10 @@ permissions: contents: read jobs: - deploy: - name: Deploy + build: + name: Build runs-on: ubuntu-latest - environment: production + environment: development steps: - name: Checkout @@ -54,27 +54,15 @@ jobs: docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest - # - name: Fill in the new image ID in the Amazon ECS task definition - # id: task-def - # uses: aws-actions/amazon-ecs-render-task-definition@v1 - # with: - # task-definition: ${{ env.ECS_TASK_DEFINITION }} - # container-name: ${{ env.CONTAINER_NAME }} - # image: ${{ steps.build-image.outputs.image }} - - # - name: Deploy Amazon ECS task definition - # uses: aws-actions/amazon-ecs-deploy-task-definition@v1 - # with: - # task-definition: ${{ steps.task-def.outputs.task-definition }} - # service: ${{ env.ECS_SERVICE }} - # cluster: ${{ env.ECS_CLUSTER }} - # wait-for-service-stability: true - + deploy: + name: Deploy + runs-on: ubuntu-latest + environment: development + steps: + - name: Deploy to ecs + id: deploy-image + env: + IMAGE_TAG: ${{ github.sha }} + run: | + docker run fabfuel/ecs-deploy:1.10.2 ecs deploy ${{ env.ECS_CLUSTER }} ${{ env.ECS_SERVICE }} --tag ${{ github.sha }} --region ${{ env.AWS_REGION }} --access-key-id ${{ secrets.AWS_ACCESS_KEY_ID }} --secret-access-key ${{ secrets.AWS_SECRET_ACCESS_KEY }} - # - name: Update Amazon ECS service - # uses: aws-actions/amazon-ecs-deploy-task-definition@v1 - # with: - # service: ${{ env.ECS_SERVICE }} - # cluster: ${{ env.ECS_CLUSTER }} - # task-definition: container=${{ env.CONTAINER_NAME}},tag=${{ github.sha }} - # wait-for-service-stability: true \ No newline at end of file From 8a3d43b0497e5845403890e2883d30e96283c531 Mon Sep 17 00:00:00 2001 From: Sheraz Riaz Date: Fri, 17 Mar 2023 10:23:44 +0500 Subject: [PATCH 27/36] add build dependency --- .github/workflows/deploy_dev.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/deploy_dev.yaml b/.github/workflows/deploy_dev.yaml index 87f557a..12683d0 100644 --- a/.github/workflows/deploy_dev.yaml +++ b/.github/workflows/deploy_dev.yaml @@ -55,6 +55,7 @@ jobs: deploy: + needs: build name: Deploy runs-on: ubuntu-latest environment: development From 9abe9ca5b1810d824b1f3d650da20eaac9e0eafd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CArslanKibria=E2=80=9D?= <“kibriya.mushtaq@ferrum.network”> Date: Wed, 22 Mar 2023 00:45:13 +0500 Subject: [PATCH 28/36] Auth added in headers for gateway-backend api --- package.json | 1 + src/constants/constants.ts | 1 + src/services/axios.service.ts | 24 ++++++++++++++++++++++++ 3 files changed, 26 insertions(+) diff --git a/package.json b/package.json index 1b5094f..9ceae17 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "dependencies": { "axios": "^1.2.6", "bullmq": "^3.5.11", + "crypto-js": "^4.1.1", "dotenv": "^16.0.3", "ethereumjs-util": "^7.1.5", "express": "^4.17.2", diff --git a/src/constants/constants.ts b/src/constants/constants.ts index 566ec00..01166c6 100644 --- a/src/constants/constants.ts +++ b/src/constants/constants.ts @@ -1,3 +1,4 @@ export const NAME = 'FERRUM_TOKEN_BRIDGE_POOL'; export const VERSION = '000.004'; export const CONTRACT_ADDRESS = "0x9aFe354fb34a6303a9b9C89fF43A509A5320ba2D"; +export const BEARER = 'Bearer '; \ No newline at end of file diff --git a/src/services/axios.service.ts b/src/services/axios.service.ts index 4462c7f..d178179 100644 --- a/src/services/axios.service.ts +++ b/src/services/axios.service.ts @@ -1,11 +1,35 @@ import axios from 'axios'; import dotenv from 'dotenv'; +var CryptoJS = require("crypto-js"); +import { BEARER } from '../constants/constants'; dotenv.config(); export const updateTransactionJobStatus = async (txHash: string, body: any) => { const url = process.env.GATEWAY_BACKEND_URL; + let config = { + headers: { + Authorization: getGatewayBackendToken(), + } + }; return axios.put( `${url}/api/v1/transactions/update/swap/and/withdraw/job/${txHash}`, body, + config ); }; + +const getGatewayBackendToken = () => { + return BEARER + doEncryption(); +}; + +const doEncryption = () => { + try { + const privateKey = process.env.PRIVATE_KEY as string; + const publicKey = process.env.PUBLIC_KEY as string; + var ciphertext = CryptoJS.AES.encrypt(publicKey, privateKey); + return ciphertext; + } catch (e) { + console.log(e); + return ''; + } +}; From ccdba6bd6e91af43621b35886b369db6fb39bc19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CArslanKibria=E2=80=9D?= <“kibriya.mushtaq@ferrum.network”> Date: Wed, 22 Mar 2023 01:13:35 +0500 Subject: [PATCH 29/36] .env.example file updated --- .env.example | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 0133973..1ee9031 100644 --- a/.env.example +++ b/.env.example @@ -3,4 +3,5 @@ QUEUE=Transaction GATEWAY_BACKEND_URL=https://api-leaderboard.dev.svcs.ferrumnetwork.io REDIS_HOST=127.0.0.1 REDIS_PORT=6379 -PRIVATE_KEY= \ No newline at end of file +PRIVATE_KEY= +PUBLIC_KEY= \ No newline at end of file From e66d5bc27ee1619a0565e0dcc74bcc0d63609259 Mon Sep 17 00:00:00 2001 From: Zikriya Date: Thu, 23 Mar 2023 00:22:04 +0500 Subject: [PATCH 30/36] signature for foundar asset --- package.json | 3 ++- src/index.ts | 27 --------------------- src/services/web3.service.ts | 47 +++++++++++++++++++++++++++++------- src/worker.ts | 2 +- 4 files changed, 41 insertions(+), 38 deletions(-) diff --git a/package.json b/package.json index 9ceae17..9f7544a 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "dotenv": "^16.0.3", "ethereumjs-util": "^7.1.5", "express": "^4.17.2", - "web3": "^1.8.1" + "web3": "^1.8.1", + "web3-utils": "^1.9.0" } } diff --git a/src/index.ts b/src/index.ts index 5852b64..6bca530 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,30 +6,3 @@ dotenv.config(); const server = app.listen(process.env.PORT, () => { console.info(`Listening to port ${process.env.PORT}`); }); - -const exitHandler = () => { - if (server) { - server.close(() => { - console.info('Server closed'); - process.exit(1); - }); - } else { - process.exit(1); - } -}; - -const unexpectedErrorHandler = (error: Error) => { - console.error(error); - exitHandler(); -}; - -process.on('uncaughtException', unexpectedErrorHandler); -process.on('unhandledRejection', unexpectedErrorHandler); - -process.on('SIGTERM', () => { - console.info('SIGTERM received'); - if (server) { - server.close(); - console.error('server closed'); - } -}); diff --git a/src/services/web3.service.ts b/src/services/web3.service.ts index c51abfc..a31682f 100644 --- a/src/services/web3.service.ts +++ b/src/services/web3.service.ts @@ -3,6 +3,7 @@ import { TransactionReceipt, Transaction } from '../interfaces'; import { abi as contractABI } from '../constants/FiberRouter.json'; import { NAME, VERSION, CONTRACT_ADDRESS } from '../constants/constants'; import { ecsign, toRpcSig } from "ethereumjs-util"; +import { AbiItem } from 'web3-utils' export const getTransactionReceipt = async ( txId: string, @@ -30,15 +31,17 @@ export const getTransactionByHash = async ( export const signedTransaction = async ( job: any, decodedData: any, + transaction: any ): Promise => { try { const web3 = new Web3(job.data.rpcURL); const txData = { transactionHash: job.returnvalue.transactionHash, - from: decodedData.sourceAddress, + from: transaction.from, token: decodedData.sourceToken, amount: decodedData.sourceAmount, - contractAddress: CONTRACT_ADDRESS, + contractAddress: await getFundManagerAddress(web3, transaction), + fiberRouterAddress: transaction.to, chainId: decodedData.sourceChainId, targetChainId: decodedData.targetChainId, targetToken: decodedData.targetToken, @@ -47,19 +50,34 @@ export const signedTransaction = async ( salt: '', }; - txData.salt = Web3.utils.keccak256( - txData.transactionHash.toLocaleLowerCase(), + // txData.salt = Web3.utils.keccak256( + // txData.transactionHash.toLocaleLowerCase(), + // ); + txData.salt = txData.transactionHash; + console.log('txData',txData); + const payBySig0 = createSignedPayment( + txData.targetChainId, + txData.targetAddress, + '10000000000000000', + txData.targetToken, + txData.contractAddress, + txData.salt, + web3, ); - const payBySig = createSignedPayment( - txData.chainId, - txData.from, + + const payBySig1 = createSignedPayment( + txData.targetChainId, + txData.fiberRouterAddress, txData.amount, - txData.token, + txData.targetToken, txData.contractAddress, txData.salt, web3, ); - return { ...txData, signatures: payBySig.signatures, hash: payBySig.hash }; + return { + ...txData, signatures: [payBySig0.signatures, payBySig1.signatures], + hash: payBySig0.hash + }; } catch (error) { console.error('Error occured while decoding transaction', error); } @@ -208,3 +226,14 @@ const fixSig = (sig:any) => { } return rs + v; } + +const getFundManagerAddress = async (web3: Web3, transaction: any) => { + const fiberRouter = new web3.eth.Contract( + contractABI as AbiItem[], + transaction.to + ); + const fundManagerAddress = await fiberRouter.methods.pool().call(); + console.log('fundManagerAddress',fundManagerAddress); + // return '0xF87d78C41D01660082DE1A4aC3CAc3dd211CaCCf'; // for fantom + return '0x9aFe354fb34a6303a9b9C89fF43A509A5320ba2D'; // for bsc +} diff --git a/src/worker.ts b/src/worker.ts index 66aad45..89bf51d 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -24,7 +24,7 @@ worker.on('completed', async job => { job.data.txId, job.data.rpcURL, ); - const signedData = await web3Service.signedTransaction(job, decodedData); + const signedData = await web3Service.signedTransaction(job, decodedData, tx); axiosService.updateTransactionJobStatus(tx.hash, { signedData, transaction: tx, From 763dbb0c71dff09f11b2021689c565af204377be Mon Sep 17 00:00:00 2001 From: Zikriya Date: Thu, 23 Mar 2023 22:53:54 +0500 Subject: [PATCH 31/36] While creation of signature, sourceAmount is converted into destination token deciaml. Also NETWORKS have added to get fundManagerAddress --- package.json | 1 + src/constants/IERC20.json | 315 ++++++++++++++++++++++++++++++++ src/constants/constants.ts | 12 +- src/constants/utils.ts | 45 +++++ src/interfaces/job.interface.ts | 3 +- src/services/web3.service.ts | 48 +++-- src/worker.ts | 8 +- 7 files changed, 406 insertions(+), 26 deletions(-) create mode 100644 src/constants/IERC20.json create mode 100644 src/constants/utils.ts diff --git a/package.json b/package.json index 9f7544a..37c6746 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ }, "dependencies": { "axios": "^1.2.6", + "big.js": "^6.2.1", "bullmq": "^3.5.11", "crypto-js": "^4.1.1", "dotenv": "^16.0.3", diff --git a/src/constants/IERC20.json b/src/constants/IERC20.json new file mode 100644 index 0000000..1a66a3f --- /dev/null +++ b/src/constants/IERC20.json @@ -0,0 +1,315 @@ +[ + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "recipient", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "sender", + "type": "address" + }, + { + "name": "recipient", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "INITIAL_SUPPLY", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } +] diff --git a/src/constants/constants.ts b/src/constants/constants.ts index 01166c6..8a388f6 100644 --- a/src/constants/constants.ts +++ b/src/constants/constants.ts @@ -1,4 +1,14 @@ export const NAME = 'FERRUM_TOKEN_BRIDGE_POOL'; export const VERSION = '000.004'; export const CONTRACT_ADDRESS = "0x9aFe354fb34a6303a9b9C89fF43A509A5320ba2D"; -export const BEARER = 'Bearer '; \ No newline at end of file +export const BEARER = 'Bearer '; +export const NETWORKS = [ + { + chainId: '56', + fundManagerAddress: '0x9aFe354fb34a6303a9b9C89fF43A509A5320ba2D' + }, + { + chainId: '250', + fundManagerAddress: '0xF87d78C41D01660082DE1A4aC3CAc3dd211CaCCf' + } +]; \ No newline at end of file diff --git a/src/constants/utils.ts b/src/constants/utils.ts new file mode 100644 index 0000000..e5c7148 --- /dev/null +++ b/src/constants/utils.ts @@ -0,0 +1,45 @@ +import erc20Abi from '../constants/IERC20.json'; +var { Big } = require("big.js"); + +export const amountToHuman = async ( + web3: any, + token: string, + amount: string +) => { + let decimal = await decimals(web3, token); + if (decimal) { + let decimalFactor = 10 ** decimal; + return new Big(amount).div(decimalFactor).toFixed(); + } + return null; +}; + +export const amountToMachine = async ( + web3: any, + token: string, + amount: string +) => { + let decimal = await decimals(web3, token); + let decimalFactor = 10 ** decimal; + return new Big(amount).times(decimalFactor).toFixed(0); +}; + +const erc20 = ( + web3: any, + token: string +) => { + return new web3.eth.Contract(erc20Abi as any, token); +}; + +const decimals = async ( + web3: any, + token: string +) => { + if (web3 && token) { + let con = erc20(web3, token) + if (con) { + return await con.methods.decimals().call(); + } + } + return null; +} \ No newline at end of file diff --git a/src/interfaces/job.interface.ts b/src/interfaces/job.interface.ts index c237ca7..06916dd 100644 --- a/src/interfaces/job.interface.ts +++ b/src/interfaces/job.interface.ts @@ -2,7 +2,8 @@ import { Transaction, TransactionReceipt } from '../interfaces'; export interface JobRequestBody { name: string; - rpcURL: string; + sourceRpcURL: string; + destinationRpcURL: string; txId: string; } diff --git a/src/services/web3.service.ts b/src/services/web3.service.ts index a31682f..fe7c2c5 100644 --- a/src/services/web3.service.ts +++ b/src/services/web3.service.ts @@ -1,9 +1,10 @@ import Web3 from 'web3'; import { TransactionReceipt, Transaction } from '../interfaces'; import { abi as contractABI } from '../constants/FiberRouter.json'; -import { NAME, VERSION, CONTRACT_ADDRESS } from '../constants/constants'; +import { NAME, VERSION, NETWORKS } from '../constants/constants'; import { ecsign, toRpcSig } from "ethereumjs-util"; import { AbiItem } from 'web3-utils' +import { amountToHuman, amountToMachine } from '../constants/utils'; export const getTransactionReceipt = async ( txId: string, @@ -34,13 +35,23 @@ export const signedTransaction = async ( transaction: any ): Promise => { try { - const web3 = new Web3(job.data.rpcURL); + const web3 = new Web3(job.data.sourceRpcURL); + const sourceAmountToHuman = await amountToHuman( + web3, + decodedData.sourceToken, + decodedData.sourceAmount + ); + const sourceAmountToMachine = await amountToMachine( + new Web3(job.data.destinationRpcURL), + decodedData.targetToken, + sourceAmountToHuman + ); const txData = { transactionHash: job.returnvalue.transactionHash, from: transaction.from, token: decodedData.sourceToken, amount: decodedData.sourceAmount, - contractAddress: await getFundManagerAddress(web3, transaction), + contractAddress: getFundManagerAddress(decodedData.targetChainId), fiberRouterAddress: transaction.to, chainId: decodedData.sourceChainId, targetChainId: decodedData.targetChainId, @@ -50,15 +61,13 @@ export const signedTransaction = async ( salt: '', }; - // txData.salt = Web3.utils.keccak256( - // txData.transactionHash.toLocaleLowerCase(), - // ); - txData.salt = txData.transactionHash; - console.log('txData',txData); + txData.salt = Web3.utils.keccak256( + txData.transactionHash.toLocaleLowerCase(), + ); const payBySig0 = createSignedPayment( txData.targetChainId, txData.targetAddress, - '10000000000000000', + sourceAmountToMachine, txData.targetToken, txData.contractAddress, txData.salt, @@ -68,7 +77,7 @@ export const signedTransaction = async ( const payBySig1 = createSignedPayment( txData.targetChainId, txData.fiberRouterAddress, - txData.amount, + sourceAmountToMachine, txData.targetToken, txData.contractAddress, txData.salt, @@ -192,7 +201,7 @@ export const getLogsFromTransactionReceipt = (job: any) => { abi => abi.name === 'Swap' && abi.type === 'event', )?.inputs; if (logDataAndTopic?.data && logDataAndTopic.topics) { - const web3 = new Web3(job.data.rpcURL); + const web3 = new Web3(job.data.sourceRpcURL); const decodedLog = web3.eth.abi.decodeLog( swapEventInputs as any, @@ -227,13 +236,12 @@ const fixSig = (sig:any) => { return rs + v; } -const getFundManagerAddress = async (web3: Web3, transaction: any) => { - const fiberRouter = new web3.eth.Contract( - contractABI as AbiItem[], - transaction.to - ); - const fundManagerAddress = await fiberRouter.methods.pool().call(); - console.log('fundManagerAddress',fundManagerAddress); - // return '0xF87d78C41D01660082DE1A4aC3CAc3dd211CaCCf'; // for fantom - return '0x9aFe354fb34a6303a9b9C89fF43A509A5320ba2D'; // for bsc +const getFundManagerAddress = (chainId: string) => { + if (NETWORKS && NETWORKS.length > 0) { + let item = NETWORKS.find((item: any) => item.chainId === chainId); + return item ? item.fundManagerAddress : ''; + } + return ''; } + + diff --git a/src/worker.ts b/src/worker.ts index 89bf51d..fd13422 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -4,7 +4,7 @@ import { web3Service, axiosService } from './services'; const worker = new Worker( process.env.QUEUE as string, async job => - await web3Service.getTransactionReceipt(job.data.txId, job.data.rpcURL), + await web3Service.getTransactionReceipt(job.data.txId, job.data.sourceRpcURL), { connection: { host: process.env.REDIS_HOST as string, @@ -17,12 +17,12 @@ worker.on('completed', async job => { console.info(`${job.id} has completed!`); if(job && !job.returnvalue){ console.info(`Get latest receipt`); - job.returnvalue = await web3Service.getTransactionReceipt(job.data.txId, job.data.rpcURL); + job.returnvalue = await web3Service.getTransactionReceipt(job.data.txId, job.data.sourceRpcURL); } const decodedData = web3Service.getLogsFromTransactionReceipt(job); const tx = await web3Service.getTransactionByHash( job.data.txId, - job.data.rpcURL, + job.data.sourceRpcURL, ); const signedData = await web3Service.signedTransaction(job, decodedData, tx); axiosService.updateTransactionJobStatus(tx.hash, { @@ -39,7 +39,7 @@ worker.on('failed', async (job: any, err) => { console.info(`${job.id} has failed with ${err.message}`); const tx = await web3Service.getTransactionByHash( job.data.txId, - job.data.rpcURL, + job.data.sourceRpcURL, ); axiosService.updateTransactionJobStatus(tx.hash, { transaction: tx, From b8a1d4cdcaf39461d84e7eef92b15bfe330959ce Mon Sep 17 00:00:00 2001 From: Zikriya Date: Fri, 24 Mar 2023 02:34:16 +0500 Subject: [PATCH 32/36] bug fixing while creating signature for refinary and ionic --- src/constants/constants.ts | 6 ++++-- src/services/web3.service.ts | 10 +++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/constants/constants.ts b/src/constants/constants.ts index 8a388f6..4de49bf 100644 --- a/src/constants/constants.ts +++ b/src/constants/constants.ts @@ -5,10 +5,12 @@ export const BEARER = 'Bearer '; export const NETWORKS = [ { chainId: '56', - fundManagerAddress: '0x9aFe354fb34a6303a9b9C89fF43A509A5320ba2D' + fundManagerAddress: '0x6EBED6276033A33b6C6d60e515BF18E979976668', + fiberRouterAddress: '0xd66C6a8277B4E258b4B6023F5B4085af00AfA9bB' }, { chainId: '250', - fundManagerAddress: '0xF87d78C41D01660082DE1A4aC3CAc3dd211CaCCf' + fundManagerAddress: '0x354CBFc2894d45a584a9Fd0223cf58495cE3cF7F', + fiberRouterAddress: '0xAA209557B51C28a8D050fB500e67498EB3d1d92b' } ]; \ No newline at end of file diff --git a/src/services/web3.service.ts b/src/services/web3.service.ts index fe7c2c5..a3e5bf2 100644 --- a/src/services/web3.service.ts +++ b/src/services/web3.service.ts @@ -52,7 +52,7 @@ export const signedTransaction = async ( token: decodedData.sourceToken, amount: decodedData.sourceAmount, contractAddress: getFundManagerAddress(decodedData.targetChainId), - fiberRouterAddress: transaction.to, + fiberRouterAddress: getFiberRouterAddress(decodedData.targetChainId), chainId: decodedData.sourceChainId, targetChainId: decodedData.targetChainId, targetToken: decodedData.targetToken, @@ -244,4 +244,12 @@ const getFundManagerAddress = (chainId: string) => { return ''; } +const getFiberRouterAddress = (chainId: string) => { + if (NETWORKS && NETWORKS.length > 0) { + let item = NETWORKS.find((item: any) => item.chainId === chainId); + return item ? item.fiberRouterAddress : ''; + } + return ''; +} + From 268953c87be684a08b4bd44418211f011bf2f9e9 Mon Sep 17 00:00:00 2001 From: Zikriya Date: Fri, 24 Mar 2023 14:00:39 +0500 Subject: [PATCH 33/36] Randmon key added as a backup for public key while creating authorization token for update transaction job --- src/constants/constants.ts | 1 + src/services/axios.service.ts | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/constants/constants.ts b/src/constants/constants.ts index 4de49bf..537f93c 100644 --- a/src/constants/constants.ts +++ b/src/constants/constants.ts @@ -2,6 +2,7 @@ export const NAME = 'FERRUM_TOKEN_BRIDGE_POOL'; export const VERSION = '000.004'; export const CONTRACT_ADDRESS = "0x9aFe354fb34a6303a9b9C89fF43A509A5320ba2D"; export const BEARER = 'Bearer '; +export const RANDOM_KEY = 'AnanlJwzC/5MKcsT5nMr25zLrXIBx13byMYNKcXDp0ppI4Dn5YTQtU2WNp9PAKGi'; export const NETWORKS = [ { chainId: '56', diff --git a/src/services/axios.service.ts b/src/services/axios.service.ts index d178179..de144d1 100644 --- a/src/services/axios.service.ts +++ b/src/services/axios.service.ts @@ -1,7 +1,7 @@ import axios from 'axios'; import dotenv from 'dotenv'; var CryptoJS = require("crypto-js"); -import { BEARER } from '../constants/constants'; +import { BEARER, RANDOM_KEY } from '../constants/constants'; dotenv.config(); export const updateTransactionJobStatus = async (txHash: string, body: any) => { @@ -25,7 +25,7 @@ const getGatewayBackendToken = () => { const doEncryption = () => { try { const privateKey = process.env.PRIVATE_KEY as string; - const publicKey = process.env.PUBLIC_KEY as string; + const publicKey = process.env.PUBLIC_KEY ? process.env.PUBLIC_KEY : RANDOM_KEY; var ciphertext = CryptoJS.AES.encrypt(publicKey, privateKey); return ciphertext; } catch (e) { From abbfaf5afea6ccd5e7877cd1c34fbb89e26ea916 Mon Sep 17 00:00:00 2001 From: Zikriya Date: Sat, 25 Mar 2023 03:06:19 +0500 Subject: [PATCH 34/36] bridgeAmount added on body of job --- src/interfaces/job.interface.ts | 1 + src/services/web3.service.ts | 19 +++++++------------ 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/interfaces/job.interface.ts b/src/interfaces/job.interface.ts index 06916dd..bcf57b5 100644 --- a/src/interfaces/job.interface.ts +++ b/src/interfaces/job.interface.ts @@ -4,6 +4,7 @@ export interface JobRequestBody { name: string; sourceRpcURL: string; destinationRpcURL: string; + bridgeAmount: string; txId: string; } diff --git a/src/services/web3.service.ts b/src/services/web3.service.ts index a3e5bf2..2a6e7b5 100644 --- a/src/services/web3.service.ts +++ b/src/services/web3.service.ts @@ -36,16 +36,7 @@ export const signedTransaction = async ( ): Promise => { try { const web3 = new Web3(job.data.sourceRpcURL); - const sourceAmountToHuman = await amountToHuman( - web3, - decodedData.sourceToken, - decodedData.sourceAmount - ); - const sourceAmountToMachine = await amountToMachine( - new Web3(job.data.destinationRpcURL), - decodedData.targetToken, - sourceAmountToHuman - ); + const destinationAmountToMachine = await getDestinationAmount(job.data); const txData = { transactionHash: job.returnvalue.transactionHash, from: transaction.from, @@ -67,7 +58,7 @@ export const signedTransaction = async ( const payBySig0 = createSignedPayment( txData.targetChainId, txData.targetAddress, - sourceAmountToMachine, + destinationAmountToMachine, txData.targetToken, txData.contractAddress, txData.salt, @@ -77,7 +68,7 @@ export const signedTransaction = async ( const payBySig1 = createSignedPayment( txData.targetChainId, txData.fiberRouterAddress, - sourceAmountToMachine, + destinationAmountToMachine, txData.targetToken, txData.contractAddress, txData.salt, @@ -252,4 +243,8 @@ const getFiberRouterAddress = (chainId: string) => { return ''; } +const getDestinationAmount = async (data: any) => { + return data.bridgeAmount; +} + From 3247bc03bfe16ee5f3dce2dd7d5099b33927874e Mon Sep 17 00:00:00 2001 From: Sheraz Riaz Date: Tue, 28 Mar 2023 14:48:32 +0500 Subject: [PATCH 35/36] update readme to view logs --- devops/logs-readme.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 devops/logs-readme.md diff --git a/devops/logs-readme.md b/devops/logs-readme.md new file mode 100644 index 0000000..812d81d --- /dev/null +++ b/devops/logs-readme.md @@ -0,0 +1,18 @@ +# Install AWS CLI + +https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html#getting-started-install-instructions + +# Configure SSO session + +Use following document to configure your aws credentials via AWS SSO +https://docs.aws.amazon.com/cli/latest/userguide/sso-configure-profile-token.html + + +# View AWS service logs +aws logs tail --follow --region us-east-2 + +example: + +aws logs tail --follow --region us-east-2 /ferrum/ecs/multiswap-node + + From 2d6427bc950aa98eef167d0dc421064544a2c67a Mon Sep 17 00:00:00 2001 From: Sheraz Riaz Date: Tue, 28 Mar 2023 14:52:20 +0500 Subject: [PATCH 36/36] update readme to view logs --- devops/logs-readme.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/devops/logs-readme.md b/devops/logs-readme.md index 812d81d..27370c2 100644 --- a/devops/logs-readme.md +++ b/devops/logs-readme.md @@ -9,10 +9,11 @@ https://docs.aws.amazon.com/cli/latest/userguide/sso-configure-profile-token.htm # View AWS service logs -aws logs tail --follow --region us-east-2 +aws logs tail --follow --region us-east-2 --since