Merge branch 'main' into v3

pull/2733/head
Yorke Rhodes 12 months ago
commit 3fc2c9cdf6
No known key found for this signature in database
GPG Key ID: 9EEACF1DA75C5627
  1. 4
      README.md
  2. 3
      package.json
  3. 62
      solidity/contracts/token/FastHypERC20.sol
  4. 61
      solidity/contracts/token/FastHypERC20Collateral.sol
  5. 21
      typescript/infra/config/aggregationIsm.ts
  6. 49
      typescript/infra/config/routingIsm.ts
  7. 2
      typescript/infra/package.json
  8. 4
      typescript/infra/scripts/module-can-verify.ts
  9. 13
      typescript/sdk/src/consts/multisigIsm.ts
  10. 2
      typescript/sdk/src/token/adapters/SealevelTokenAdapter.ts
  11. 3
      typescript/utils/.mocharc.json
  12. 6
      typescript/utils/package.json
  13. 105
      typescript/utils/src/amount.ts
  14. 87
      typescript/utils/src/big-numbers.test.ts
  15. 76
      typescript/utils/src/big-numbers.ts
  16. 7
      typescript/utils/src/multisig.ts
  17. 37
      yarn.lock

@ -14,9 +14,9 @@
Note this is the branch for Hyperlane v3.
V2 is on the main branch but is eventually being phased out.
V2 is still in operation but is not being actively developed. The code for V2 can be found in the [v2](https://github.com/hyperlane-xyz/hyperlane-monorepo/tree/v2) branch.
V1 has since been deprecated in favor of V2, but if you are looking for code relating to the existing V1 deployments of the `testnet2` or `mainnet` environments, refer to the [v1](https://github.com/hyperlane-xyz/hyperlane-monorepo/tree/v1) branch.
V1 has since been deprecated in favor of V2, but if you are looking for code relating to the existing V1 deployments, refer to the [v1](https://github.com/hyperlane-xyz/hyperlane-monorepo/tree/v1) branch.
## Overview

@ -37,6 +37,7 @@
"lodash": "^4.17.21",
"recursive-readdir": "^2.2.3",
"underscore": "^1.13",
"undici": "^5.11"
"undici": "^5.11",
"@trivago/prettier-plugin-sort-imports/@babel/parser": "^7.22.7"
}
}

@ -0,0 +1,62 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.0;
import {HypERC20} from "./HypERC20.sol";
import {TokenRouter} from "./libs/TokenRouter.sol";
import {FastTokenRouter} from "./libs/FastTokenRouter.sol";
import {TokenMessage} from "./libs/TokenMessage.sol";
import {ERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
/**
* @title Hyperlane ERC20 Token Router that extends ERC20 with remote transfer functionality.
* @author Abacus Works
* @dev Supply on each chain is not constant but the aggregate supply across all chains is.
*/
contract FastHypERC20 is FastTokenRouter, HypERC20 {
constructor(
uint8 __decimals,
address _mailbox
) HypERC20(__decimals, _mailbox) {}
/**
* @dev delegates transfer logic to `_transferTo`.
* @inheritdoc TokenRouter
*/
function _handle(
uint32 _origin,
bytes32 _sender,
bytes calldata _message
) internal virtual override(FastTokenRouter, TokenRouter) {
FastTokenRouter._handle(_origin, _sender, _message);
}
/**
* @dev Mints `_amount` of tokens to `_recipient`.
* @inheritdoc FastTokenRouter
*/
function _fastTransferTo(
address _recipient,
uint256 _amount
) internal override {
_mint(_recipient, _amount);
}
/**
* @dev Burns `_amount` of tokens from `_recipient`.
* @inheritdoc FastTokenRouter
*/
function _fastRecieveFrom(
address _sender,
uint256 _amount
) internal override {
_burn(_sender, _amount);
}
function balanceOf(
address _account
) public view virtual override(TokenRouter, HypERC20) returns (uint256) {
return HypERC20.balanceOf(_account);
}
}

@ -0,0 +1,61 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.0;
import {HypERC20Collateral} from "./HypERC20Collateral.sol";
import {TokenRouter} from "./libs/TokenRouter.sol";
import {FastTokenRouter} from "./libs/FastTokenRouter.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
/**
* @title Hyperlane ERC20 Token Collateral that wraps an existing ERC20 with remote transfer functionality.
* @author Abacus Works
*/
contract FastHypERC20Collateral is FastTokenRouter, HypERC20Collateral {
using SafeERC20 for IERC20;
/**
* @notice Constructor
* @param erc20 Address of the token to keep as collateral
* @param _mailbox Address of the mailbox address
*/
constructor(
address erc20,
address _mailbox
) HypERC20Collateral(erc20, _mailbox) {}
/**
* @dev delegates transfer logic to `_transferTo`.
* @inheritdoc FastTokenRouter
*/
function _handle(
uint32 _origin,
bytes32 _sender,
bytes calldata _message
) internal virtual override(FastTokenRouter, TokenRouter) {
FastTokenRouter._handle(_origin, _sender, _message);
}
/**
* @dev Transfers `_amount` of `wrappedToken` to `_recipient`.
* @inheritdoc FastTokenRouter
*/
function _fastTransferTo(
address _recipient,
uint256 _amount
) internal override {
wrappedToken.safeTransfer(_recipient, _amount);
}
/**
* @dev Transfers in `_amount` of `wrappedToken` from `_recipient`.
* @inheritdoc FastTokenRouter
*/
function _fastRecieveFrom(
address _sender,
uint256 _amount
) internal override {
wrappedToken.safeTransferFrom(_sender, address(this), _amount);
}
}

@ -1,21 +0,0 @@
import { AggregationIsmConfig, ChainName } from '@hyperlane-xyz/sdk';
import { IsmType } from '@hyperlane-xyz/sdk/dist/ism/types';
import { Contexts } from './contexts';
import { multisigIsm } from './multisigIsm';
// Merkle Root Message ID
export const aggregationIsm = (
remote: ChainName,
context: Contexts,
): AggregationIsmConfig => {
return {
type: IsmType.AGGREGATION,
modules: [
// Ordering matters to preserve determinism
multisigIsm(remote, IsmType.MERKLE_ROOT_MULTISIG, context),
multisigIsm(remote, IsmType.MESSAGE_ID_MULTISIG, context),
],
threshold: 1,
};
};

@ -4,30 +4,31 @@ import {
ChainName,
IsmConfig,
IsmType,
ModuleType,
RoutingIsmConfig,
TestChains,
} from '@hyperlane-xyz/sdk';
import { DeployEnvironment } from '../src/config';
import { aggregationIsm } from './aggregationIsm';
import { Contexts } from './contexts';
import { supportedChainNames as mainnet3Chains } from './environments/mainnet3/chains';
import { owners as mainnet3Owners } from './environments/mainnet3/owners';
import { chainNames as testChains } from './environments/test/chains';
import { owners as testOwners } from './environments/test/owners';
import { supportedChainNames as testnet4Chains } from './environments/testnet4/chains';
import { owners as testnet4Owners } from './environments/testnet4/owners';
const chains = {
mainnet3: mainnet3Chains,
testnet4: testnet4Chains,
test: testChains,
};
import { multisigIsm } from './multisigIsm';
const owners = {
test: testOwners,
testnet4: testnet4Owners,
mainnet3: mainnet3Owners,
test: testOwners,
};
const chains = {
test: TestChains,
testnet4: testnet4Chains,
mainnet3: mainnet3Chains,
};
// Intended to be the "entrypoint" ISM.
@ -58,16 +59,38 @@ export const routingIsm = (
};
};
// Aggregation (1/2)
// | |
// | |
// v v
// Merkle Root Message ID
export const aggregationIsm = (
remote: ChainName,
context: Contexts,
): AggregationIsmConfig => {
return {
type: IsmType.AGGREGATION,
modules: [
// Ordering matters to preserve determinism
multisigIsm(remote, IsmType.MERKLE_ROOT_MULTISIG, context),
multisigIsm(remote, IsmType.MESSAGE_ID_MULTISIG, context),
],
threshold: 1,
};
};
const replacerEnum = (key: string, value: any) => {
if (key === 'type') {
switch (value) {
case IsmType.AGGREGATION:
case ModuleType.AGGREGATION:
return 'AGGREGATION';
case IsmType.ROUTING:
case ModuleType.ROUTING:
return 'ROUTING';
case IsmType.MERKLE_ROOT_MULTISIG:
case ModuleType.MERKLE_ROOT_MULTISIG:
return 'MERKLE_ROOT_MULTISIG';
case IsmType.MESSAGE_ID_MULTISIG:
case ModuleType.LEGACY_MULTISIG:
return 'LEGACY_MULTISIG';
case ModuleType.MESSAGE_ID_MULTISIG:
return 'MESSAGE_ID_MULTISIG';
default:
return value;

@ -33,7 +33,7 @@
"@types/node": "^16.9.1",
"@types/prompts": "^2.0.14",
"@types/sinon-chai": "^3.2.12",
"@types/yargs": "^17.0.10",
"@types/yargs": "^17.0.24",
"chai": "^4.3.4",
"ethereum-waffle": "^4.0.10",
"ethers": "^5.7.2",

@ -5,10 +5,6 @@ import { deployEnvToSdkEnv } from '../src/config/environment';
import { getArgs, getEnvironmentConfig } from './utils';
// Hacky temporary script just to make sure that default ISMs are correct.
// Testnet3 has already been updated, mainnet3 hasn't, so the above cache
// is used for mainnet3.
async function main() {
const args = await getArgs().argv;

@ -77,11 +77,6 @@ export const defaultMultisigConfigs: ChainMap<MultisigConfig> = {
'0xdb96116d13a2fadde9742d7cc88474a5ed39a03a', // everstake
],
},
// solana: {
// threshold: 0,
// validators: [
// ],
// },
base: {
threshold: 2,
validators: [
@ -106,6 +101,14 @@ export const defaultMultisigConfigs: ChainMap<MultisigConfig> = {
'0x57231619fea13d85270ca6943298046c75a6dd01', // everstake
],
},
solana: {
threshold: 2,
validators: [
'0x3cd1a081f38874bbb075bf10b62adcb858db864c', // abacus
'0x2b0c45f6111ae1c1684d4287792e3bd6ebd1abcc', // ZKV
'0x7b9ec253a8ba38994457eb9dbe386938d545351a', // everstake
],
},
// ----------------- Testnets -----------------
alfajores: {
threshold: 2,

@ -162,7 +162,7 @@ export class SealevelTokenAdapter
// we generously request 1M units.
const TRANSFER_REMOTE_COMPUTE_LIMIT = 1_000_000;
abstract class SealevelHypTokenAdapter
export abstract class SealevelHypTokenAdapter
extends SealevelTokenAdapter
implements IHypTokenAdapter
{

@ -0,0 +1,3 @@
{
"require": ["ts-node/register"]
}

@ -6,7 +6,8 @@
"@cosmjs/encoding": "^0.31.3",
"@solana/web3.js": "^1.78.0",
"bignumber.js": "^9.1.1",
"ethers": "^5.7.2"
"ethers": "^5.7.2",
"mocha": "^10.2.0"
},
"devDependencies": {
"chai": "^4.3.0",
@ -27,7 +28,8 @@
"build": "tsc",
"clean": "rm -rf ./dist",
"check": "tsc --noEmit",
"prettier": "prettier --write ./src"
"prettier": "prettier --write ./src",
"test:unit": "mocha --config .mocharc.json './src/**/*.test.ts'"
},
"sideEffects": false,
"types": "dist/index.d.ts",

@ -6,31 +6,39 @@ const DEFAULT_MIN_ROUNDED_VALUE = 0.00001;
const DEFAULT_DISPLAY_DECIMALS = 4;
const DEFAULT_TOKEN_DECIMALS = 18;
type NumberT = BigNumber.Value;
// Use toString(10) on bignumber.js to prevent ethers.js bigNumber error
// when parsing exponential string over e21
/**
* Convert the given Wei value to Ether value
* @param value The value to convert.
* @returns Converted value in string type.
*/
export function fromWei(
value: NumberT | null | undefined,
value: BigNumber.Value | null | undefined,
decimals = DEFAULT_TOKEN_DECIMALS,
): number {
if (!value) return 0;
const valueString = value.toString().trim();
const flooredValue = new BigNumber(valueString).toFixed(
0,
BigNumber.ROUND_FLOOR,
);
return parseFloat(formatUnits(flooredValue, decimals));
): string {
if (!value) return (0).toString();
const valueString = value.toString(10).trim();
const flooredValue = BigNumber(valueString).toFixed(0, BigNumber.ROUND_FLOOR);
return parseFloat(formatUnits(flooredValue, decimals)).toString();
}
// Similar to fromWei above but rounds to set number of decimals
// with a minimum floor, configured per token
/**
* Convert the given Wei value to Ether value,
* round to set number of decimals with a minimum floor, configured per token
* @param value The value to convert.
* @param decimals
* @returns Converted value in string type.
*/
export function fromWeiRounded(
value: NumberT | null | undefined,
value: BigNumber.Value | null | undefined,
decimals = DEFAULT_TOKEN_DECIMALS,
roundDownIfSmall = true,
): string {
if (!value) return '0';
const flooredValue = new BigNumber(value).toFixed(0, BigNumber.ROUND_FLOOR);
const amount = new BigNumber(formatUnits(flooredValue, decimals));
const flooredValue = BigNumber(value).toFixed(0, BigNumber.ROUND_FLOOR);
const amount = BigNumber(formatUnits(flooredValue, decimals));
if (amount.isZero()) return '0';
// If amount is less than min value
@ -40,38 +48,49 @@ export function fromWeiRounded(
}
const displayDecimals = amount.gte(10000) ? 2 : DEFAULT_DISPLAY_DECIMALS;
return amount.toFixed(displayDecimals).toString();
return amount.toFixed(displayDecimals);
}
/**
* Convert the given value to Wei value
* @param value The value to convert.
* @returns Converted value in string type.
*/
export function toWei(
value: NumberT | null | undefined,
value: BigNumber.Value | null | undefined,
decimals = DEFAULT_TOKEN_DECIMALS,
): BigNumber {
if (!value) return new BigNumber(0);
): string {
if (!value) return BigNumber(0).toString();
// First convert to a BigNumber, and then call `toString` with the
// explicit radix 10 such that the result is formatted as a base-10 string
// and not in scientific notation.
const valueBN = new BigNumber(value);
const valueBN = BigNumber(value);
const valueString = valueBN.toString(10).trim();
const components = valueString.split('.');
if (components.length === 1) {
return new BigNumber(parseUnits(valueString, decimals).toString());
return parseUnits(valueString, decimals).toString();
} else if (components.length === 2) {
const trimmedFraction = components[1].substring(0, decimals);
return new BigNumber(
parseUnits(`${components[0]}.${trimmedFraction}`, decimals).toString(),
);
return parseUnits(
`${components[0]}.${trimmedFraction}`,
decimals,
).toString();
} else {
throw new Error(`Cannot convert ${valueString} to wei`);
}
}
/**
* Try to parse the given value into BigNumber.js BigNumber
* @param value The value to parse.
* @returns Parsed value in BigNumber.js BigNumber type.
*/
export function tryParseAmount(
value: NumberT | null | undefined,
value: BigNumber.Value | null | undefined,
): BigNumber | null {
try {
if (!value) return null;
const parsed = new BigNumber(value);
const parsed = BigNumber(value);
if (!parsed || parsed.isNaN() || !parsed.isFinite()) return null;
else return parsed;
} catch (error) {
@ -79,15 +98,20 @@ export function tryParseAmount(
}
}
// Checks if an amount is equal of nearly equal to balance within a small margin of error
// Necessary because amounts in the UI are often rounded
/**
* Checks if an amount is equal of nearly equal to balance within a small margin of error
* Necessary because amounts in the UI are often rounded
* @param amountInWei1 The amount to compare.
* @param amountInWei2 The amount to compare.
* @returns true/false.
*/
export function eqAmountApproximate(
amountInWei1: BigNumber,
amountInWei2: NumberT,
) {
amountInWei1: BigNumber.Value,
amountInWei2: BigNumber.Value,
): boolean {
const minValueWei = toWei(DEFAULT_MIN_ROUNDED_VALUE);
// Is difference btwn amount and balance less than min amount shown for token
return amountInWei1.minus(amountInWei2).abs().lt(minValueWei);
return BigNumber(amountInWei1).minus(amountInWei2).abs().lt(minValueWei);
}
/**
@ -96,26 +120,27 @@ export function eqAmountApproximate(
* @param fromDecimals The number of decimals `value` has.
* @param toDecimals The number of decimals to convert `value` to.
* @param value The value to convert.
* @returns `value` represented with `toDecimals` decimals.
* @returns `value` represented with `toDecimals` decimals in string type.
*/
export function convertDecimals(
fromDecimals: number,
toDecimals: number,
value: NumberT,
) {
const amount = new BigNumber(value);
value: BigNumber.Value,
): string {
const amount = BigNumber(value);
if (fromDecimals === toDecimals) return amount;
if (fromDecimals === toDecimals) return amount.toString(10);
else if (fromDecimals > toDecimals) {
const difference = fromDecimals - toDecimals;
return amount
.div(new BigNumber(10).pow(difference))
.integerValue(BigNumber.ROUND_FLOOR);
.div(BigNumber(10).pow(difference))
.integerValue(BigNumber.ROUND_FLOOR)
.toString(10);
}
// fromDecimals < toDecimals
else {
const difference = toDecimals - fromDecimals;
return amount.times(new BigNumber(10).pow(difference));
return amount.times(BigNumber(10).pow(difference)).toString(10);
}
}

@ -1,15 +1,70 @@
import BigNumber from 'bignumber.js';
import { expect } from 'chai';
import { BigNumber, FixedNumber } from 'ethers';
import { FixedNumber } from 'ethers';
import { bigToFixed, fixedToBig, mulBigAndFixed } from './big-numbers';
import {
BigNumberMax,
BigNumberMin,
bigToFixed,
fixedToBig,
isBigNumberish,
isZeroish,
mulBigAndFixed,
} from './big-numbers';
describe('utils', () => {
describe('isBigNumberish', () => {
const testCases = [
{ expect: false, context: 'invalid number', case: 'invalidNumber' },
{ expect: false, context: 'NaN', case: NaN },
{ expect: false, context: 'undefined', case: undefined },
{ expect: false, context: 'null', case: null },
{ expect: true, context: 'decimal', case: 123.123 },
{ expect: true, context: 'integer', case: 300_000 },
{ expect: true, context: 'hex 0', case: 0x00 },
{ expect: true, context: 'hex 0', case: 0x000 },
{
expect: true,
context: 'address 0',
case: 0x0000000000000000000000000000000000000000,
},
];
testCases.forEach((tc) => {
it(`returns ${tc.expect} for ${tc.case}`, () => {
expect(isBigNumberish(tc.case!)).to.equal(tc.expect);
});
});
});
describe('isZeroish', () => {
const testCases = [
{ expect: false, context: 'invalid number', case: 'invalidNumber' },
{ expect: false, context: 'NaN', case: NaN },
{ expect: false, context: 'undefined', case: undefined },
{ expect: false, context: 'null', case: null },
{ expect: false, context: 'non 0 decimal', case: 123.123 },
{ expect: false, context: 'non 0 integer', case: 123 },
{ expect: true, context: 'hex 0', case: 0x00 },
{ expect: true, context: 'hex 0', case: 0x000 },
{
expect: true,
context: 'address 0',
case: 0x0000000000000000000000000000000000000000,
},
];
testCases.forEach((tc) => {
it(`returns ${tc.expect} for ${tc.case}`, () => {
expect(isZeroish(tc.case!)).to.equal(tc.expect);
});
});
});
describe('bigToFixed', () => {
it('converts a BigNumber to a FixedNumber', () => {
const big = BigNumber.from('1234');
const big = BigNumber('7.5e-10');
const fixed = bigToFixed(big);
expect(fixed.toUnsafeFloat()).to.equal(1234);
expect(fixed.toUnsafeFloat()).to.equal(7.5e-10);
});
});
@ -31,19 +86,35 @@ describe('utils', () => {
describe('mulBigAndFixed', () => {
it('gets the floored product of a BigNumber and FixedNumber', () => {
const big = BigNumber.from('1000');
const big = BigNumber('1000');
const fixed = FixedNumber.from('1.2345');
const product = mulBigAndFixed(big, fixed);
expect(product.toNumber()).to.equal(1234);
expect(product).to.equal((1234).toString());
});
it('gets the ceilinged product of a BigNumber and FixedNumber', () => {
const big = BigNumber.from('1000');
const big = BigNumber('1000');
const fixed = FixedNumber.from('1.2345');
const product = mulBigAndFixed(big, fixed, true);
expect(product.toNumber()).to.equal(1235);
expect(product).to.equal((1235).toString());
});
});
describe('BigNumberMin', () => {
it('gets the min between the two BigNumber', () => {
const big = BigNumber('1000');
const bigger = BigNumber('10000');
expect(BigNumberMin(big, bigger)).to.equal(big.toString());
});
});
describe('BigNumberMax', () => {
it('gets the max between the two BigNumber', () => {
const big = BigNumber('1000');
const bigger = BigNumber('10000');
expect(BigNumberMax(big, bigger)).to.equal(bigger.toString());
});
});
});

@ -1,26 +1,33 @@
import { BigNumber, BigNumberish, FixedNumber, constants } from 'ethers';
import BigNumber from 'bignumber.js';
import { FixedNumber } from 'ethers';
import { isNullish } from './typeof';
// Use toString(10) on bignumber.js to prevent ethers.js bigNumber error
// when parsing exponential string over e21
export function isBigNumberish(value: any): value is BigNumberish {
/**
* Check if a value is bigNumberish (e.g. valid numbers, bigNumber).
* @param value The value to check.
* @returns true/false.
*/
export function isBigNumberish(
value: BigNumber.Value | undefined | null,
): boolean {
try {
if (isNullish(value)) return false;
return BigNumber.from(value)._isBigNumber;
const val = BigNumber(value!);
return !val.isNaN() && val.isFinite() && BigNumber.isBigNumber(val);
} catch (error) {
return false;
}
}
// If a value (e.g. hex string or number) is zeroish (0, 0x0, 0x00, etc.)
export function isZeroish(value: BigNumberish) {
/**
* Check if a value (e.g. hex string or number) is zeroish (0, 0x0, 0x00, etc.).
* @param value The value to check.
* @returns true/false.
*/
export function isZeroish(value: BigNumber.Value): boolean {
try {
if (
!value ||
value === constants.HashZero ||
value === constants.AddressZero
)
return true;
return BigNumber.from(value).isZero();
return BigNumber(value).isZero();
} catch (error) {
return false;
}
@ -31,8 +38,8 @@ export function isZeroish(value: BigNumberish) {
* @param big The BigNumber to convert.
* @returns A FixedNumber representation of a BigNumber.
*/
export function bigToFixed(big: BigNumber): FixedNumber {
return FixedNumber.from(big.toString());
export function bigToFixed(big: BigNumber.Value): FixedNumber {
return FixedNumber.from(big.toString(10));
}
/**
@ -43,7 +50,7 @@ export function bigToFixed(big: BigNumber): FixedNumber {
*/
export function fixedToBig(fixed: FixedNumber, ceil = false): BigNumber {
const fixedAsInteger = ceil ? fixed.ceiling() : fixed.floor();
return BigNumber.from(fixedAsInteger.toFormat('fixed256x0').toString());
return BigNumber(fixedAsInteger.toFormat('fixed256x0').toString());
}
/**
@ -51,21 +58,40 @@ export function fixedToBig(fixed: FixedNumber, ceil = false): BigNumber {
* @param big The BigNumber to multiply.
* @param fixed The FixedNumber to multiply.
* @param ceil If true, the ceiling of the product is used. Otherwise, the floor is used.
* @returns The BigNumber product.
* @returns The BigNumber product in string type.
*/
export function mulBigAndFixed(
big: BigNumber,
big: BigNumber.Value,
fixed: FixedNumber,
ceil = false,
): BigNumber {
): string {
// Converts big to a FixedNumber, multiplies it by fixed, and converts the product back
// to a BigNumber.
return fixedToBig(fixed.mulUnsafe(bigToFixed(big)), ceil);
return fixedToBig(fixed.mulUnsafe(bigToFixed(big)), ceil).toString(10);
}
export function BigNumberMin(bn1: BigNumber, bn2: BigNumber) {
return bn1.gte(bn2) ? bn2 : bn1;
/**
* Return the smaller in the given two BigNumbers.
* @param bn1 The BigNumber to compare.
* @param bn2 The BigNumber to compare.
* @returns The smaller BigNumber in string type.
*/
export function BigNumberMin(
bn1: BigNumber.Value,
bn2: BigNumber.Value,
): string {
return BigNumber(bn1).gte(bn2) ? bn2.toString(10) : bn1.toString(10);
}
export function BigNumberMax(bn1: BigNumber, bn2: BigNumber) {
return bn1.lte(bn2) ? bn2 : bn1;
/**
* Return the bigger in the given two BigNumbers.
* @param bn1 The BigNumber to compare.
* @param bn2 The BigNumber to compare.
* @returns The bigger BigNumber in string type.
*/
export function BigNumberMax(
bn1: BigNumber.Value,
bn2: BigNumber.Value,
): string {
return BigNumber(bn1).lte(bn2) ? bn2.toString(10) : bn1.toString(10);
}

@ -1,4 +1,5 @@
import { BigNumber, utils } from 'ethers';
import BigNumber from 'bignumber.js';
import { utils } from 'ethers';
import { addressToBytes32 } from './addresses';
import { ParsedLegacyMultisigIsmMetadata } from './types';
@ -18,7 +19,7 @@ export const parseLegacyMultisigIsmMetadata = (
const checkpointRoot = utils.hexlify(
buf.slice(MERKLE_ROOT_OFFSET, MERKLE_INDEX_OFFSET),
);
const checkpointIndex = BigNumber.from(
const checkpointIndex = BigNumber(
utils.hexlify(buf.slice(MERKLE_INDEX_OFFSET, ORIGIN_MAILBOX_OFFSET)),
).toNumber();
const originMailbox = utils.hexlify(
@ -30,7 +31,7 @@ export const parseLegacyMultisigIsmMetadata = (
);
};
const proof = parseBytesArray(MERKLE_PROOF_OFFSET, 32, 32);
const threshold = BigNumber.from(
const threshold = BigNumber(
utils.hexlify(buf.slice(THRESHOLD_OFFSET, SIGNATURES_OFFSET)),
).toNumber();
const signatures = parseBytesArray(

@ -2546,21 +2546,30 @@ __metadata:
languageName: node
linkType: hard
"@babel/parser@npm:^7.20.5, @babel/parser@npm:^7.23.0":
version: 7.23.3
resolution: "@babel/parser@npm:7.23.3"
"@babel/parser@npm:^7.22.15":
version: 7.22.16
resolution: "@babel/parser@npm:7.22.16"
bin:
parser: ./bin/babel-parser.js
checksum: 284c22ec1d939df66fb94929959d2160c30df1ba5778f212668dfb2f4aa8ac176f628c6073a2c9ea7ab2a1701d2ebdafb0dfb173dc737db9dc6708d5d2f49e0a
checksum: 220df7dc0dbe8bc73540e66123f9c45ae3e5db40738fc1e97579205364240bed3e9724fc737c0828f9d46c96ce9b23728314f598e5bf8a62566ccef539d15bdf
languageName: node
linkType: hard
"@babel/parser@npm:^7.22.15":
version: 7.22.16
resolution: "@babel/parser@npm:7.22.16"
"@babel/parser@npm:^7.22.7":
version: 7.22.7
resolution: "@babel/parser@npm:7.22.7"
bin:
parser: ./bin/babel-parser.js
checksum: 220df7dc0dbe8bc73540e66123f9c45ae3e5db40738fc1e97579205364240bed3e9724fc737c0828f9d46c96ce9b23728314f598e5bf8a62566ccef539d15bdf
checksum: f420f89ea8e5803a44f76a57630002ca5721fbde719c10ac4eaebf1d01fad102447cd90a7721c97b1176bde33ec9bc2b68fe8c7d541668dc6610727ba79c8862
languageName: node
linkType: hard
"@babel/parser@npm:^7.23.0":
version: 7.23.3
resolution: "@babel/parser@npm:7.23.3"
bin:
parser: ./bin/babel-parser.js
checksum: 284c22ec1d939df66fb94929959d2160c30df1ba5778f212668dfb2f4aa8ac176f628c6073a2c9ea7ab2a1701d2ebdafb0dfb173dc737db9dc6708d5d2f49e0a
languageName: node
linkType: hard
@ -4095,7 +4104,7 @@ __metadata:
"@types/node": "npm:^16.9.1"
"@types/prompts": "npm:^2.0.14"
"@types/sinon-chai": "npm:^3.2.12"
"@types/yargs": "npm:^17.0.10"
"@types/yargs": "npm:^17.0.24"
asn1.js: "npm:5.4.1"
aws-kms-ethers-signer: "npm:^0.1.3"
chai: "npm:^4.3.4"
@ -4182,6 +4191,7 @@ __metadata:
bignumber.js: "npm:^9.1.1"
chai: "npm:^4.3.0"
ethers: "npm:^5.7.2"
mocha: "npm:^10.2.0"
prettier: "npm:^2.8.8"
typescript: "npm:5.1.6"
languageName: unknown
@ -6156,15 +6166,6 @@ __metadata:
languageName: node
linkType: hard
"@types/yargs@npm:^17.0.10":
version: 17.0.31
resolution: "@types/yargs@npm:17.0.31"
dependencies:
"@types/yargs-parser": "npm:*"
checksum: 9b180fc289cc7342a584e9e552dd667d60e6e0a436be67ed8feee681cb22de1ebffacd6a1e29c5905049850c10bb1c9db45d957cfd01a97f58b33e290b233b1f
languageName: node
linkType: hard
"@types/yargs@npm:^17.0.24":
version: 17.0.24
resolution: "@types/yargs@npm:17.0.24"

Loading…
Cancel
Save