diff --git a/.changeset/afraid-rivers-swim.md b/.changeset/afraid-rivers-swim.md new file mode 100644 index 00000000..d62f3682 --- /dev/null +++ b/.changeset/afraid-rivers-swim.md @@ -0,0 +1,9 @@ +--- +'@rosen-chains/bitcoin-esplora': patch +'@rosen-chains/bitcoin': patch +'@rosen-chains/cardano': patch +'@rosen-chains/ergo': patch +'@rosen-chains/evm': patch +--- + +improve logs diff --git a/packages/chains/bitcoin/lib/BitcoinChain.ts b/packages/chains/bitcoin/lib/BitcoinChain.ts index 56974b4a..ed4fd31b 100644 --- a/packages/chains/bitcoin/lib/BitcoinChain.ts +++ b/packages/chains/bitcoin/lib/BitcoinChain.ts @@ -312,7 +312,7 @@ class BitcoinChain extends AbstractUtxoChain { ); if (feeDifferencePercent > this.configs.txFeeSlippage) { this.logger.warn( - `Fee difference is high. Slippage is higher than allowed value [${feeDifferencePercent} > ${this.configs.txFeeSlippage}]. fee: ${fee}, estimated fee: ${estimatedFee}` + `Tx [${transaction.txId}] is not verified: Fee difference is too high. Slippage is higher than allowed value [${feeDifferencePercent} > ${this.configs.txFeeSlippage}]. fee: ${fee}, estimated fee: ${estimatedFee}` ); return false; } @@ -346,8 +346,8 @@ class BitcoinChain extends AbstractUtxoChain { const changeBoxIndex = tx.txOutputs.length - 1; const changeBox = tx.txOutputs[changeBoxIndex]; if (changeBox.script.toString('hex') !== this.lockScript) { - this.logger.debug( - `Tx [${transaction.txId}] invalid: Change box address is wrong` + this.logger.warn( + `Tx [${transaction.txId}] is not verified: Change box address is wrong` ); return false; } @@ -382,7 +382,7 @@ class BitcoinChain extends AbstractUtxoChain { for (let i = 0; i < tx.txInputs.length; i++) { const boxId = getPsbtTxInputBoxId(tx.txInputs[i]); if (!(await this.network.isBoxUnspentAndValid(boxId))) { - this.logger.debug( + this.logger.info( `Tx [${transaction.txId}] is invalid due to spending invalid input box [${boxId}] at index [${i}]` ); return { diff --git a/packages/chains/cardano/lib/CardanoChain.ts b/packages/chains/cardano/lib/CardanoChain.ts index d0c662fd..8e680a27 100644 --- a/packages/chains/cardano/lib/CardanoChain.ts +++ b/packages/chains/cardano/lib/CardanoChain.ts @@ -495,6 +495,9 @@ class CardanoChain extends AbstractUtxoChain { // check ttl const ttl = txBody.ttl(); if (ttl && ttl < (await this.network.currentSlot())) { + this.logger.info( + `Tx [${transaction.txId}] is invalid: ttl [${ttl}] is expired` + ); return { isValid: false, details: { @@ -508,7 +511,7 @@ class CardanoChain extends AbstractUtxoChain { for (let i = 0; i < txBody.inputs().len(); i++) { const boxId = CardanoUtils.getBoxId(txBody.inputs().get(i)); if (!(await this.network.isBoxUnspentAndValid(boxId))) { - this.logger.debug( + this.logger.info( `Tx [${transaction.txId}] is invalid due to spending invalid input box [${boxId}] at index [${i}]` ); return { @@ -563,8 +566,8 @@ class CardanoChain extends AbstractUtxoChain { if ( tx.body().fee().compare(CardanoUtils.bigIntToBigNum(this.configs.fee)) > 0 ) { - this.logger.debug( - `Tx [${transaction.txId}] invalid: Transaction fee [${tx + this.logger.warn( + `Tx [${transaction.txId}] is not verified: Transaction fee [${tx .body() .fee() .to_str()}] is more than maximum allowed fee [${this.configs.fee.toString()}]` @@ -586,7 +589,9 @@ class CardanoChain extends AbstractUtxoChain { // check metadata if (tx.auxiliary_data()) { - this.logger.debug(`Tx [${transaction.txId}] invalid: Contains metadata`); + this.logger.warn( + `Tx [${transaction.txId}] is not verified: Contains metadata` + ); return false; } @@ -594,8 +599,8 @@ class CardanoChain extends AbstractUtxoChain { const changeBoxIndex = tx.body().outputs().len() - 1; const changeBox = tx.body().outputs().get(changeBoxIndex); if (changeBox.address().to_bech32() !== this.configs.addresses.lock) { - this.logger.debug( - `Tx [${transaction.txId}] invalid: Change box address is wrong` + this.logger.warn( + `Tx [${transaction.txId}] is not verified: Change box address is wrong` ); return false; } diff --git a/packages/chains/ergo/lib/ErgoChain.ts b/packages/chains/ergo/lib/ErgoChain.ts index 5341ecda..0b19a0d9 100644 --- a/packages/chains/ergo/lib/ErgoChain.ts +++ b/packages/chains/ergo/lib/ErgoChain.ts @@ -513,8 +513,8 @@ class ErgoChain extends AbstractUtxoChain { const box = outputBoxes.get(i); if (box.ergo_tree().to_base16_bytes() === ErgoChain.feeBoxErgoTree) { if (BigInt(box.value().as_i64().to_str()) > this.configs.fee) { - this.logger.debug( - `Tx [${transaction.txId}] invalid: Transaction fee [${box + this.logger.warn( + `Tx [${transaction.txId}] is not verified: Transaction fee [${box .value() .as_i64() .to_str()}] is more than maximum allowed fee [${ @@ -545,8 +545,8 @@ class ErgoChain extends AbstractUtxoChain { blockInfo.height - box.creation_height() > NUMBER_OF_BLOCKS_PER_YEAR ) { - this.logger.info( - `Lock tx [${transaction.id().to_str()}] is not valid, box [${box + this.logger.error( + `Lock tx [${transaction.id().to_str()}] is not verified, box [${box .box_id() .to_str()}] creation_height [${box.creation_height()}] is more than a year ago` ); @@ -581,10 +581,10 @@ class ErgoChain extends AbstractUtxoChain { const r4Value = output.register_value(4); if (r4Value) { - this.logger.debug( + this.logger.warn( `Tx [${ transaction.txId - }] is invalid. Change box at index [${i}] has value [${r4Value.encode_to_base16()}] in R4` + }] is not verified: Change box at index [${i}] has value [${r4Value.encode_to_base16()}] in R4` ); return false; } @@ -618,7 +618,7 @@ class ErgoChain extends AbstractUtxoChain { for (let i = 0; i < inputs.len(); i++) { const boxId = inputs.get(i).box_id().to_str(); if (!(await this.network.isBoxUnspentAndValid(boxId))) { - this.logger.debug( + this.logger.info( `Tx [${transaction.txId}] is invalid due to spending invalid input box [${boxId}] at index [${i}]` ); return { diff --git a/packages/chains/evm/lib/EvmChain.ts b/packages/chains/evm/lib/EvmChain.ts index f3186212..f80d6764 100644 --- a/packages/chains/evm/lib/EvmChain.ts +++ b/packages/chains/evm/lib/EvmChain.ts @@ -27,6 +27,7 @@ import { Signature, Transaction } from 'ethers'; import Serializer from './Serializer'; import * as EvmUtils from './EvmUtils'; import { AbstractLogger } from '@rosen-bridge/abstract-logger'; +import JsonBigInt from '@rosen-bridge/json-bigint'; abstract class EvmChain extends AbstractChain { declare network: AbstractEvmNetwork; @@ -80,8 +81,12 @@ abstract class EvmChain extends AbstractChain { unsignedTransactions: PaymentTransaction[], serializedSignedTransactions: string[] ): Promise => { - // split orders + // split orders and aggregate const orders = EvmUtils.splitPaymentOrders(order); + let orderRequiredAssets: AssetBalance = { + nativeToken: 0n, + tokens: [], + }; orders.forEach((singleOrder) => { if (singleOrder.assets.tokens.length === 1) { const assetId = singleOrder.assets.tokens[0].id; @@ -90,8 +95,15 @@ abstract class EvmChain extends AbstractChain { `Asset id [${assetId}] is not supported` ); } + orderRequiredAssets = ChainUtils.sumAssetBalance( + orderRequiredAssets, + singleOrder.assets + ); } }); + this.logger.debug( + `Order required assets: ${JsonBigInt.stringify(orderRequiredAssets)}` + ); // check the number of parallel transactions won't be exceeded let nextNonce = await this.network.getAddressNextAvailableNonce( @@ -182,9 +194,8 @@ abstract class EvmChain extends AbstractChain { } // check the balance in the lock address - const requiredAssets: AssetBalance = orders.reduce( - (sum: AssetBalance, order: SinglePayment) => - ChainUtils.sumAssetBalance(sum, order.assets), + const requiredAssets: AssetBalance = ChainUtils.sumAssetBalance( + orderRequiredAssets, { nativeToken: this.tokenMap.wrapAmount( this.NATIVE_TOKEN_ID, @@ -194,6 +205,9 @@ abstract class EvmChain extends AbstractChain { tokens: [], } ); + this.logger.debug( + `Required assets: ${JsonBigInt.stringify(requiredAssets)}` + ); if (!(await this.hasLockAddressEnoughAssets(requiredAssets))) { const neededETH = requiredAssets.nativeToken.toString(); @@ -351,19 +365,23 @@ abstract class EvmChain extends AbstractChain { try { tx = Serializer.deserialize(transaction.txBytes); } catch (error) { - this.logger.debug(`Tx [${transaction.txId}] invalid: ${error}`); + this.logger.warn( + `Failed to deserialize tx [${transaction.txId}]: ${error}` + ); return false; } if (tx.to === null) { - this.logger.debug( - `Tx [${transaction.txId}] invalid: does not have \`to\`` + this.logger.warn( + `Tx [${transaction.txId}] is not verified: does not have \`to\`` ); return false; } if (tx.type !== 2) { - this.logger.debug(`Tx [${transaction.txId}] invalid: is not of type 2`); + this.logger.warn( + `Tx [${transaction.txId}] is not verified: is not of type 2` + ); return false; } @@ -382,7 +400,7 @@ abstract class EvmChain extends AbstractChain { // check gas limit let estimatedRequiredGas = await this.network.getGasRequired(tx); if (estimatedRequiredGas > this.configs.gasLimitCap) { - this.logger.debug( + this.logger.info( `Estimated required gas is more than gas limit cap config and cap is used for verification [${estimatedRequiredGas} > ${this.configs.gasLimitCap}]` ); estimatedRequiredGas = this.configs.gasLimitCap; @@ -396,8 +414,8 @@ abstract class EvmChain extends AbstractChain { : gasRequired - tx.gasLimit; if (gasDifference > gasLimitSlippage) { - this.logger.debug( - `Tx [${transaction.txId}] invalid: Transaction gas limit [${tx.gasLimit}] is too far from calculated gas limit [${gasRequired}]` + this.logger.warn( + `Tx [${transaction.txId}] is not verified: Transaction gas limit [${tx.gasLimit}] is too far from calculated gas limit [${gasRequired}]` ); return false; } @@ -412,8 +430,8 @@ abstract class EvmChain extends AbstractChain { : networkMaxFee - tx.maxFeePerGas; if (maxFeeDifference > maxFeeSlippage) { - this.logger.debug( - `Tx [${transaction.txId}] invalid: Transaction max fee [${tx.maxFeePerGas}] is too far from network's max fee [${networkMaxFee}]` + this.logger.warn( + `Tx [${transaction.txId}] is not verified: Transaction max fee [${tx.maxFeePerGas}] is too far from network's max fee [${networkMaxFee}]` ); return false; } @@ -427,8 +445,8 @@ abstract class EvmChain extends AbstractChain { : networkMaxPriorityFee - tx.maxPriorityFeePerGas; if (maxPriorityFeeDifference > priorityFeeSlippage) { - this.logger.debug( - `Tx [${transaction.txId}] invalid: Transaction max priority fee [${tx.maxPriorityFeePerGas}] is too far from network's max priority fee [${networkMaxPriorityFee}]` + this.logger.warn( + `Tx [${transaction.txId}] is not verified: Transaction max priority fee [${tx.maxPriorityFeePerGas}] is too far from network's max priority fee [${networkMaxPriorityFee}]` ); return false; } @@ -452,8 +470,8 @@ abstract class EvmChain extends AbstractChain { try { trx = Serializer.deserialize(transaction.txBytes); } catch (error) { - this.logger.debug( - `Tx [${transaction.txId}] invalid: failed to deserialized due to error: ${error}` + this.logger.warn( + `Tx [${transaction.txId}] is invalid: failed to deserialized due to error: ${error}` ); return { isValid: false, @@ -467,8 +485,8 @@ abstract class EvmChain extends AbstractChain { // check if tx is failed const txStatus = await this.network.getTransactionStatus(transaction.txId); if (txStatus === EvmTxStatus.failed) { - this.logger.debug( - `Tx [${transaction.txId}] invalid: tx is failed in blockchain` + this.logger.info( + `Tx [${transaction.txId}] is invalid: tx is failed in blockchain` ); return { isValid: false, @@ -491,8 +509,8 @@ abstract class EvmChain extends AbstractChain { details: undefined, }; } - this.logger.debug( - `Tx [${transaction.txId}] invalid: Transaction's nonce [${trx.nonce}] is not available anymore according to address's current nonce [${nextNonce}]` + this.logger.info( + `Tx [${transaction.txId}] is invalid: Transaction's nonce [${trx.nonce}] is not available anymore according to address's current nonce [${nextNonce}]` ); return { isValid: false, @@ -564,7 +582,9 @@ abstract class EvmChain extends AbstractChain { try { tx = Serializer.deserialize(transaction.txBytes); } catch (error) { - this.logger.debug(`Tx [${transaction.txId}] invalid: ${error}`); + this.logger.warn( + `Failed to deserialize tx [${transaction.txId}]: ${error}` + ); return; } @@ -705,7 +725,9 @@ abstract class EvmChain extends AbstractChain { const tx = Serializer.deserialize(transaction.txBytes); if (tx.to === null) { - this.logger.debug(`Tx [${transaction.txId}] is invalid. \`to\` is null`); + this.logger.warn( + `Tx [${transaction.txId}] is not verified. \`to\` is null` + ); return false; } @@ -717,16 +739,16 @@ abstract class EvmChain extends AbstractChain { // only type 2 transactions are allowed if (tx.type !== 2) { - this.logger.debug( - `Tx [${transaction.txId}] is invalid. It is not of type 2` + this.logger.warn( + `Tx [${transaction.txId}] is not verified. It is not of type 2` ); return false; } // tx data must have correct length if (![eidlen + 2, eidlen + 2 + 136].includes(tx.data.length)) { - this.logger.debug( - `Tx [${transaction.txId}] is invalid. Unexpected \`data\` bytes length [${tx.data.length}]` + this.logger.warn( + `Tx [${transaction.txId}] is not verified. Unexpected \`data\` bytes length [${tx.data.length}]` ); return false; } @@ -734,8 +756,8 @@ abstract class EvmChain extends AbstractChain { // eventId must be at the end of `data` const eventId = tx.data.substring(tx.data.length - eidlen); if (eventId !== transaction.eventId) { - this.logger.debug( - `Tx [${transaction.txId}] is invalid. Encoded eventId [${eventId}] does not match with the expected one [${transaction.eventId}]` + this.logger.warn( + `Tx [${transaction.txId}] is not verified. Encoded eventId [${eventId}] does not match with the expected one [${transaction.eventId}]` ); return false; } @@ -745,8 +767,8 @@ abstract class EvmChain extends AbstractChain { (tx.value === 0n && tx.data.length === eidlen + 2) || (tx.value !== 0n && tx.data.length === 136 + eidlen + 2) ) { - this.logger.debug( - `Tx [${transaction.txId}] is invalid. It both transfers native-token and has extra data.` + this.logger.warn( + `Tx [${transaction.txId}] is not verified. It both transfers native-token and has extra data.` ); return false; } @@ -754,8 +776,8 @@ abstract class EvmChain extends AbstractChain { // only erc-20 `transfer` is allowed if (tx.value === 0n) { if (!EvmUtils.isTransfer(tx.to, tx.data)) { - this.logger.debug( - `Tx [${transaction.txId}] is invalid. \`data\` field [${tx.data}] can not be parsed with 'transfer' ABI.` + this.logger.warn( + `Tx [${transaction.txId}] is not verified. \`data\` field [${tx.data}] can not be parsed with 'transfer' ABI.` ); return false; } @@ -782,7 +804,7 @@ abstract class EvmChain extends AbstractChain { ); const txStatus = await this.network.getTransactionStatus(transaction.hash); if (txStatus !== EvmTxStatus.succeed) { - this.logger.debug( + this.logger.error( `Lock tx [${transaction.hash}] is not succeed (failed or unexpected status)` ); return false; diff --git a/packages/networks/bitcoin-esplora/lib/BitcoinEsploraNetwork.ts b/packages/networks/bitcoin-esplora/lib/BitcoinEsploraNetwork.ts index cc8880ac..8e5d3435 100644 --- a/packages/networks/bitcoin-esplora/lib/BitcoinEsploraNetwork.ts +++ b/packages/networks/bitcoin-esplora/lib/BitcoinEsploraNetwork.ts @@ -416,9 +416,7 @@ class BitcoinEsploraNetwork extends AbstractBitcoinNetwork { .get>(`/api/mempool/txids`) .then((res) => { this.logger.debug( - `requested 'mempool/txids'. received: ${JsonBigInt.stringify( - res.data - )}` + `requested 'mempool/txids'. received [${res.data.length}] txs` ); return res.data; })