Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

fix: erc20 update total supply #863

Merged
merged 4 commits into from
Jul 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 1 addition & 15 deletions src/services/evm/erc20.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { QueryModuleAccountByNameResponseSDKType } from '@aura-nw/aurajs/types/codegen/cosmos/auth/v1beta1/query';
import {
Action,
Service,
Expand All @@ -9,7 +8,7 @@ import { Context, ServiceBroker } from 'moleculer';
import { PublicClient, getContract } from 'viem';
import config from '../../../config.json' assert { type: 'json' };
import BullableService, { QueueHandler } from '../../base/bullable.service';
import { SERVICE as COSMOS_SERVICE, Config, getLcdClient } from '../../common';
import { SERVICE as COSMOS_SERVICE, Config } from '../../common';
import knex from '../../common/utils/db_connection';
import { getViemClient } from '../../common/utils/etherjs_client';
import { BlockCheckpoint, EVMSmartContract } from '../../models';
Expand All @@ -28,8 +27,6 @@ const { NODE_ENV } = Config;
export default class Erc20Service extends BullableService {
viemClient!: PublicClient;

erc20ModuleAccount!: string;

public constructor(public broker: ServiceBroker) {
super(broker);
}
Expand Down Expand Up @@ -352,17 +349,6 @@ export default class Erc20Service extends BullableService {
public async _start(): Promise<void> {
this.viemClient = getViemClient();
if (NODE_ENV !== 'test') {
if (config.evmOnly === false) {
const lcdClient = await getLcdClient();
const erc20Account: QueryModuleAccountByNameResponseSDKType =
await lcdClient.provider.cosmos.auth.v1beta1.moduleAccountByName({
name: 'erc20',
});
Erc20Handler.erc20ModuleAccount =
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
erc20Account.account.base_account.address;
}
await this.createJob(
BULL_JOB_NAME.HANDLE_ERC20_CONTRACT,
BULL_JOB_NAME.HANDLE_ERC20_CONTRACT,
Expand Down
128 changes: 88 additions & 40 deletions src/services/evm/erc20_handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@ import Moleculer from 'moleculer';
import { decodeAbiParameters, keccak256, toHex } from 'viem';
import config from '../../../config.json' assert { type: 'json' };
import knex from '../../common/utils/db_connection';
import { Erc20Activity, Event, EventAttribute, EvmEvent } from '../../models';
import {
Erc20Activity,
Erc20Contract,
Event,
EventAttribute,
EvmEvent,
} from '../../models';
import { AccountBalance } from '../../models/account_balance';
import { ZERO_ADDRESS } from './constant';
import { convertBech32AddressToEthAddress } from './utils';
Expand Down Expand Up @@ -56,14 +62,16 @@ export class Erc20Handler {

erc20Activities: Erc20Activity[];

static erc20ModuleAccount: any;
erc20Contracts: Dictionary<Erc20Contract>;

constructor(
accountBalances: Dictionary<AccountBalance>,
erc20Activities: Erc20Activity[]
erc20Activities: Erc20Activity[],
erc20Contracts: Dictionary<Erc20Contract>
) {
this.accountBalances = accountBalances;
this.erc20Activities = erc20Activities;
this.erc20Contracts = erc20Contracts;
}

process() {
Expand All @@ -81,37 +89,60 @@ export class Erc20Handler {
}

handlerErc20Transfer(erc20Activity: Erc20Activity) {
const erc20Contract: Erc20Contract =
this.erc20Contracts[erc20Activity.erc20_contract_address];
if (!erc20Contract) {
throw new Error(
`Erc20 contract not found:${ erc20Activity.erc20_contract_address}`
);
}
// update from account balance if from != ZERO_ADDRESS
if (erc20Activity.from !== ZERO_ADDRESS) {
const fromAccountId = erc20Activity.from_account_id;
const key = `${fromAccountId}_${erc20Activity.erc20_contract_address}`;
const fromAccountBalance = this.accountBalances[key];
if (
!fromAccountBalance ||
fromAccountBalance.last_updated_height <= erc20Activity.height
fromAccountBalance &&
erc20Activity.height < fromAccountBalance.last_updated_height
) {
// calculate new balance: decrease balance of from account
const amount = (
BigInt(fromAccountBalance?.amount || 0) - BigInt(erc20Activity.amount)
throw new Error(
`Process erc20 balance: fromAccountBalance ${erc20Activity.from} was updated`
);
}
// calculate new balance: decrease balance of from account
const amount = (
BigInt(fromAccountBalance?.amount || 0) - BigInt(erc20Activity.amount)
).toString();
// update object accountBalance
this.accountBalances[key] = AccountBalance.fromJson({
denom: erc20Activity.erc20_contract_address,
amount,
last_updated_height: erc20Activity.height,
account_id: fromAccountId,
type: AccountBalance.TYPE.ERC20_TOKEN,
});
} else if (erc20Contract.total_supply !== null) {
// update total supply
erc20Contract.total_supply = (
BigInt(erc20Contract.total_supply) + BigInt(erc20Activity.amount)
).toString();
// update object accountBalance
this.accountBalances[key] = AccountBalance.fromJson({
denom: erc20Activity.erc20_contract_address,
amount,
last_updated_height: erc20Activity.height,
account_id: fromAccountId,
type: AccountBalance.TYPE.ERC20_TOKEN,
});
// update last updated height
erc20Contract.last_updated_height = erc20Activity.height;
}
// update from account balance if to != ZERO_ADDRESS
if (erc20Activity.to !== ZERO_ADDRESS) {
// update to account balance
const toAccountId = erc20Activity.to_account_id;
const key = `${toAccountId}_${erc20Activity.erc20_contract_address}`;
const toAccountBalance = this.accountBalances[key];
if (
toAccountBalance &&
erc20Activity.height < toAccountBalance.last_updated_height
) {
throw new Error(
`Process erc20 balance: toAccountBalance ${erc20Activity.to} was updated`
);
}
}
// update to account balance
const toAccountId = erc20Activity.to_account_id;
const key = `${toAccountId}_${erc20Activity.erc20_contract_address}`;
const toAccountBalance = this.accountBalances[key];
if (
!toAccountBalance ||
toAccountBalance.last_updated_height <= erc20Activity.height
) {
// calculate new balance: increase balance of to account
const amount = (
BigInt(toAccountBalance?.amount || 0) + BigInt(erc20Activity.amount)
Expand All @@ -124,7 +155,14 @@ export class Erc20Handler {
account_id: toAccountId,
type: AccountBalance.TYPE.ERC20_TOKEN,
});
}
} else if (erc20Contract.total_supply !== null) {
// update total supply
erc20Contract.total_supply = (
BigInt(erc20Contract.total_supply) - BigInt(erc20Activity.amount)
).toString();
// update last updated height
erc20Contract.last_updated_height = erc20Activity.height;
}
}

static async buildErc20Activities(
Expand Down Expand Up @@ -159,9 +197,6 @@ export class Erc20Handler {
);
let erc20CosmosEvents: Event[] = [];
if (config.evmOnly === false) {
if (!this.erc20ModuleAccount) {
throw new Error('erc20 module account undefined');
}
erc20CosmosEvents = await Event.query()
.transacting(trx)
.where('event.block_height', '>', startBlock)
Expand Down Expand Up @@ -202,7 +237,6 @@ export class Erc20Handler {
erc20CosmosEvents.forEach((event) => {
const activity = Erc20Handler.buildTransferActivityByCosmos(
event,
this.erc20ModuleAccount,
logger
);
if (activity) {
Expand Down Expand Up @@ -271,9 +305,30 @@ export class Erc20Handler {
),
(o) => `${o.account_id}_${o.denom}`
);
const erc20Contracts = _.keyBy(
await Erc20Contract.query()
.transacting(trx)
.whereIn(
'address',
erc20Activities.map((e) => e.erc20_contract_address)
),
'address'
);
// construct cw721 handler object
const erc20Handler = new Erc20Handler(accountBalances, erc20Activities);
const erc20Handler = new Erc20Handler(
accountBalances,
erc20Activities,
erc20Contracts
);
erc20Handler.process();
const updatedErc20Contracts = Object.values(erc20Handler.erc20Contracts);
if (updatedErc20Contracts.length > 0) {
await Erc20Contract.query()
.transacting(trx)
.insert(updatedErc20Contracts)
.onConflict(['id'])
.merge();
}
const updatedAccountBalances = Object.values(
erc20Handler.accountBalances
);
Expand Down Expand Up @@ -320,7 +375,6 @@ export class Erc20Handler {

static buildTransferActivityByCosmos(
e: Event,
erc20ModuleAccount: string,
logger: Moleculer.LoggerInstance
): Erc20Activity | undefined {
try {
Expand Down Expand Up @@ -352,15 +406,9 @@ export class Erc20Handler {
);
const sender = from;
if (e.type === Event.EVENT_TYPE.CONVERT_COIN) {
from = convertBech32AddressToEthAddress(
config.networkPrefixAddress,
erc20ModuleAccount
).toLowerCase();
from = ZERO_ADDRESS;
} else if (e.type === Event.EVENT_TYPE.CONVERT_ERC20) {
to = convertBech32AddressToEthAddress(
config.networkPrefixAddress,
erc20ModuleAccount
).toLowerCase();
to = ZERO_ADDRESS;
}
const amount = e.attributes.find(
(attr) => attr.key === EventAttribute.ATTRIBUTE_KEY.AMOUNT
Expand Down
Loading
Loading