Replace foundry with HyperlaneCoreDeployer (#28)

This PR replaces foundry with the SDK deployment tooling.

To deploy hyperlane to a new chain, users add their `ChainMetadata` to `config/chains.ts`, and their `MultisigIsmConfig(s)` to `config/multisig_ism.ts`, and run:
```
yarn ts-node scripts/deploy.ts --local foochain --remotes goerli mumbai --key 0x1234...
```

This script deploys core, IGP, ISM, and TestRecipient contracts to the local chain, and IGP, ISM, and TestRecipient contracts to the remote chains, writing contract addresses to `artifacts/addresses.json`, and agent config to `artifacts/agent_config.json`

Users can test their deployment by running:
```
yarn ts-node scripts/test-messages.ts --chains foochain goerli mumbai --key 0x1234...
```

This script dispatches messages between each pair of provided chains, regularly polling the mailboxes to check to see if they were delivered.
asaj/ci-2
Asa Oines 2 years ago committed by GitHub
parent b839529296
commit 1fdf00846f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 9
      .github/workflows/ci.yml
  2. 8
      .gitignore
  3. 4
      .gitmodules
  4. 60
      README.md
  5. 22
      artifacts/addresses.json
  6. 84
      ci.sh
  7. 24
      config/chains.ts
  8. 96
      config/multisig_ism.json
  9. 19
      config/multisig_ism.ts
  10. 119
      config/networks.json
  11. 24
      config/start_blocks.ts
  12. 14
      foundry.toml
  13. 80
      lib/BytesLib.sol
  14. 105
      lib/CheckLib.sol
  15. 247
      lib/ConfigLib.sol
  16. 165
      lib/DeployLib.sol
  17. 1
      lib/forge-std
  18. 20
      package.json
  19. 42
      scripts/CheckMessage.s.sol
  20. 35
      scripts/DeployCore.s.sol
  21. 39
      scripts/DeployMultisigIsm.s.sol
  22. 44
      scripts/SendTestMessage.s.sol
  23. 18
      scripts/deploy.ts
  24. 167
      scripts/test-messages.ts
  25. 53
      src/TestRecipientDeployer.ts
  26. 159
      src/config.ts
  27. 172
      src/deployer.ts
  28. 37
      src/json.ts
  29. 28
      tsconfig.json
  30. 340
      yarn.lock

@ -12,9 +12,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
submodules: recursive
- uses: actions/cache@v3
with:
path: '**/node_modules'
@ -32,7 +29,7 @@ jobs:
exit 1
fi
build:
deploy:
needs: [yarn-install]
runs-on: ubuntu-latest
steps:
@ -47,8 +44,8 @@ jobs:
with:
version: nightly
- name: Build
run: forge build
- name: deploy
run: ./ci.sh
lint:
needs: [yarn-install]

8
.gitignore vendored

@ -1,6 +1,4 @@
node_modules/
broadcast/
out/
forge-cache/
cache/
config/*_agent_config.json
dist/
artifacts/
.yarn*

4
.gitmodules vendored

@ -1,4 +0,0 @@
[submodule "lib/forge-std"]
path = lib/forge-std
url = https://github.com/foundry-rs/forge-std
tag = v1.1.1

@ -14,61 +14,43 @@ For more detailed instructions on how to deploy Hyperlane to the EVM chain of yo
### Setup
- Installing foundry
See https://github.com/foundry-rs/foundry#installation
- Installing dependencies
```bash
yarn install
git submodule init && git submodule update --remote
```
### Deploying core contracts
### Deploying contracts
This script is used to incrementally deploy the core Hyperlane smart contracts to a new chain.
If you're deploying to a new chain, ensure there is a corresponding entry `config/networks.ts` and `config/multisig_ism.ts`.
If a contract address for `$LOCAL` is set to `0x0` in `./config/networks.json`, that contract will be deployed. If not, the script will assert that the contract is configured according to the config in `./config`.
This script is used to deploy the following core Hyperlane contracts to a new chain.
The Hyperlane protocol expects exactly one instance of these contracts on every supported chain.
If you're deploying to a new chain, ensure there is a corresponding entry for `$LOCAL` in `./config/networks.json` with all contract addresses set to `0x0`.
- A `Mailbox` for sending and receiving messages
- `ValidatorAnnounce` for registering validators
The script deploys:
This script also deploys the following contracts to all chains, new and existing.
The Hyperlane protocol expects many instances of these contracts on every supported chains
- A `ProxyAdmin`, used to administer `TransparentUpgradableProxies` for `Mailbox` and `InterchainGasPaymaster`
- A `Mailbox`, which applications can use to send and receive messages
- A `MultisigIsm`. Applications can optionally use this ISM to verify interchain messages sent to the local chain.
- An `InterchainGasPaymaster`. Applications can optionally use this contract to pay a relayer to deliver their interchain messages to remote chains.
- A `TestRecipient`. Users can send messages to this contract to verify that everything is working properly.
- An `ISM` (MultisigISM) for verifying inbound messages from remote chains
- An `InterchainGasPaymaster` for paying relayers for message delivery
- A `TestRecipient` contract that can be used to test that interchain messages can be delivered
```bash
# The name of the chain to deploy to. Used to configure the localDomain for the
# Mailbox contract.
export LOCAL=YOUR_CHAIN_NAME
# An RPC url for the chain to deploy to.
export RPC_URL=YOUR_CHAIN_RPC_URL
# The comma separated name(s) of the chains to receive messages from.
# Used to configure the default MultisigIsm.
export REMOTES=ethereum,polygon,avalanche,celo,arbitrum,optimism,bsc,moonbeam
# Pass whatever wallet option you would like to use https://book.getfoundry.sh/reference/forge/forge-script#wallet-options---raw
forge script scripts/DeployCore.s.sol --broadcast --rpc-url $RPC_URL
DEBUG=hyperlane* yarn ts-node script scripts/deploy.ts --local anvil \
--remotes goerli sepolia \
--key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
```
### Deploying a MultisigIsm
This script is used to deploy a `MultigsigIsm` to the chain of your choice. It will be initialized to verify messages from `$REMOTES` using the config for each remote chain specified in `./config/multisig_ism.json`.
### Sending test messages
Applications can optionally use this ISM to verify interchain messages.
This script is used to verify that Hyperlane messages can be sent between specified chains.
The script will also deploy a `TestRecipient`, configured to use the deployed ISM.
Users should have first deployed `TestRecipient` contracts to each of the specified chains.
```bash
# This address will wind up owning the MultisigIsm after it's deployed.
export OWNER=0x1234
# An RPC url for the chain to deploy to.
export RPC_URL=YOUR_CHAIN_RPC_URL
# The comma separated name(s) of the chain(s) to receive messages from.
export REMOTES=YOUR_CHAIN_NAME
forge script scripts/DeployMultisigIsm.s.sol --broadcast --rpc-url $RPC_URL --private-key $PRIVATE_KEY
```
DEBUG=hyperlane* yarn ts-node scripts/test-messages.ts \
--chains anvil goerli sepolia \
--key 0x6f0311f4a0722954c46050bb9f088c4890999e16b64ad02784d24b5fd6d09061
```

@ -0,0 +1,22 @@
{
"anvil1": {
"validatorAnnounce": "0x38a024C0b412B9d1db8BC398140D00F5Af3093D4",
"proxyAdmin": "0xD42912755319665397FF090fBB63B1a31aE87Cee",
"mailbox": "0x525C7063E7C20997BaaE9bDa922159152D0e8417",
"multisigIsm": "0xCA8c8688914e0F7096c920146cd0Ad85cD7Ae8b9",
"testRecipient": "0x976fcd02f7C4773dd89C309fBF55D5923B4c98a1",
"storageGasOracle": "0xfcDB4564c18A9134002b9771816092C9693622e3",
"interchainGasPaymaster": "0x32EEce76C2C2e8758584A83Ee2F522D4788feA0f",
"defaultIsmInterchainGasPaymaster": "0x02b0B4EFd909240FCB2Eb5FAe060dC60D112E3a4"
},
"anvil2": {
"multisigIsm": "0xF32D39ff9f6Aa7a7A64d7a4F00a54826Ef791a55",
"testRecipient": "0x976fcd02f7C4773dd89C309fBF55D5923B4c98a1",
"proxyAdmin": "0xD42912755319665397FF090fBB63B1a31aE87Cee",
"storageGasOracle": "0xfcDB4564c18A9134002b9771816092C9693622e3",
"interchainGasPaymaster": "0x32EEce76C2C2e8758584A83Ee2F522D4788feA0f",
"defaultIsmInterchainGasPaymaster": "0x02b0B4EFd909240FCB2Eb5FAe060dC60D112E3a4",
"validatorAnnounce": "0x5FeaeBfB4439F3516c74939A9D04e95AFE82C4ae",
"mailbox": "0xB0f05d25e41FbC2b52013099ED9616f1206Ae21B"
}
}

84
ci.sh

@ -0,0 +1,84 @@
for CHAIN in anvil1 anvil2
do
mkdir ./artifacts/$CHAIN ./artifacts/$CHAIN/state \
./artifacts/$CHAIN/validator ./artifacts/$CHAIN/relayer
chmod 777 ./artifacts/$CHAIN -R
done
anvil --chain-id 31337 -p 8545 --state ./artifacts/anvil1/state > /dev/null &
ANVIL_1_PID=$!
anvil --chain-id 31338 -p 8555 --state ./artifacts/anvil2/state > /dev/null &
ANVIL_2_PID=$!
sleep 1
set -e
for i in "anvil1 anvil2 --no-write-agent-config" "anvil2 anvil1 --write-agent-config"
do
set -- $i
echo "Deploying contracts to $1"
DEBUG=hyperlane* yarn ts-node scripts/deploy.ts --local $1 --remotes $2 \
--key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 $3
done
for i in "anvil1 8545 ANVIL1" "anvil2 8555 ANVIL2"
do
set -- $i
echo "Running validator on $1"
# Won't work on anything but linux due to -net=host
docker run --mount type=bind,source="$(pwd)/artifacts",target=/config --net=host \
-e CONFIG_FILES=/config/agent_config.json -e HYP_VALIDATOR_ORIGINCHAINNAME=$1 \
-e HYP_VALIDATOR_REORGPERIOD=1 -e HYP_VALIDATOR_INTERVAL=1 \
-e HYP_BASE_CHAINS_${3}_CONNECTION_URL=http://127.0.0.1:${2} \
-e HYP_VALIDATOR_VALIDATOR_TYPE=hexKey \
-e HYP_VALIDATOR_VALIDATOR_KEY=0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6 \
-e HYP_VALIDATOR_CHECKPOINTSYNCER_TYPE=localStorage \
-e HYP_VALIDATOR_CHECKPOINTSYNCER_PATH=/config/${1}/validator \
-e HYP_BASE_TRACING_LEVEL=info -e HYP_BASE_TRACING_FMT=pretty \
gcr.io/abacus-labs-dev/hyperlane-agent:5bf8aed-20230323-140136 ./validator &
done
sleep 10
for i in "anvil1 8545" "anvil2 8555"
do
set -- $i
echo "Announcing validator on $1"
VALIDATOR_ANNOUNCE_ADDRESS=$(cat ./artifacts/addresses.json | jq -r ".$1.validatorAnnounce")
VALIDATOR=$(cat ./artifacts/$1/validator/announcement.json | jq -r '.value.validator')
STORAGE_LOCATION=$(cat ./artifacts/$1/validator/announcement.json | jq -r '.value.storage_location')
SIGNATURE=$(cat ./artifacts/$1/validator/announcement.json | jq -r '.serialized_signature')
cast send $VALIDATOR_ANNOUNCE_ADDRESS \
"announce(address, string calldata, bytes calldata)(bool)" \
$VALIDATOR $STORAGE_LOCATION $SIGNATURE --rpc-url http://127.0.0.1:$2 \
--private-key 0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba
done
for i in "anvil1 anvil2 ANVIL2" "anvil2 anvil1 ANVIL1"
do
set -- $i
echo "Running relayer on $1"
docker run --mount type=bind,source="$(pwd)/artifacts",target=/config --net=host \
-e CONFIG_FILES=/config/agent_config.json \
-e HYP_BASE_CHAINS_ANVIL1_CONNECTION_URL=http://127.0.0.1:8545 \
-e HYP_BASE_CHAINS_ANVIL2_CONNECTION_URL=http://127.0.0.1:8555 \
-e HYP_BASE_TRACING_LEVEL=info -e HYP_BASE_TRACING_FMT=pretty \
-e HYP_RELAYER_ORIGINCHAINNAME=$1 -e HYP_RELAYER_DESTINATIONCHAINNAMES=$2 \
-e HYP_RELAYER_ALLOWLOCALCHECKPOINTSYNCERS=true -e HYP_RELAYER_DB=/config/$1/relayer \
-e HYP_RELAYER_GASPAYMENTENFORCEMENT='[{"type":"none"}]' \
-e HYP_BASE_CHAINS_${3}_SIGNER_TYPE=hexKey \
-e HYP_BASE_CHAINS_${3}_SIGNER_KEY=0xdbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97 \
gcr.io/abacus-labs-dev/hyperlane-agent:5bf8aed-20230323-140136 ./relayer &
done
DEBUG=hyperlane* yarn ts-node scripts/test-messages.ts --chains anvil1 anvil2 --key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 --timeout 60
docker ps -aq | xargs docker stop | xargs docker rm
kill $ANVIL_1_PID
kill $ANVIL_2_PID

@ -0,0 +1,24 @@
import { ChainMap, ChainMetadata } from '@hyperlane-xyz/sdk';
export const chains: ChainMap<ChainMetadata> = {
// ----------- Your chains here -----------------
anvil: {
name: 'anvil1',
// anvil default chain id
chainId: 31337,
publicRpcUrls: [
{
http: 'http://127.0.0.1:8545',
},
],
},
anvil2: {
name: 'anvil2',
chainId: 31338,
publicRpcUrls: [
{
http: 'http://127.0.0.1:8555',
},
],
},
};

@ -1,96 +0,0 @@
{
"foochain": {
"threshold": 1,
"validators": ["0xb17861defd784d13c257f2430c4724ffa7ffc554"]
},
"alfajores": {
"threshold": 2,
"validators": [
"0xe6072396568e73ce6803b12b7e04164e839f1e54",
"0x9f177f51289b22515f41f95872e1511391b8e105",
"0x15f77400845eb1c971ad08de050861d5508cad6c"
]
},
"fuji": {
"threshold": 2,
"validators": [
"0x9fa19ead5ec76e437948b35e227511b106293c40",
"0x227e7d6507762ece0c94678f8c103eff9d682476",
"0x2379e43740e4aa4fde48cf4f00a3106df1d8420d"
]
},
"mumbai": {
"threshold": 2,
"validators": [
"0x0a664ea799447da6b15645cf8b9e82072a68343f",
"0x6ae6f12929a960aba24ba74ea310e3d37d0ac045",
"0x51f70c047cd73bc7873273707501568857a619c4"
]
},
"bsctestnet": {
"threshold": 2,
"validators": [
"0x23338c8714976dd4a57eaeff17cbd26d7e275c08",
"0x85a618d7450ebc37e0d682371f08dac94eec7a76",
"0x95b76562e4ba1791a27ba4236801271c9115b141"
]
},
"goerli": {
"threshold": 2,
"validators": [
"0xf43fbd072fd38e1121d4b3b0b8a35116bbb01ea9",
"0xa33020552a21f35e75bd385c6ab95c3dfa82d930",
"0x0bba4043ff242f8bf3f39bafa8930a84d644d947"
]
},
"moonbasealpha": {
"threshold": 2,
"validators": [
"0x890c2aeac157c3f067f3e42b8afc797939c59a32",
"0x1b06d6fe69b972ed7420c83599d5a5c0fc185904",
"0xe70b85206a968a99a597581f0fa09c99e7681093"
]
},
"optimismgoerli": {
"threshold": 2,
"validators": [
"0xbb8d77eefbecc55db6e5a19b0fc3dc290776f189",
"0x69792508b4ddaa3ca52241ccfcd1e0b119a1ee65",
"0x11ddb46c6b653e0cdd7ad5bee32ae316e18f8453"
]
},
"arbitrumgoerli": {
"threshold": 2,
"validators": [
"0xce798fa21e323f6b24d9838a10ffecdefdfc4f30",
"0xa792d39dca4426927e0f00c1618d61c9cb41779d",
"0xdf181fcc11dfac5d01467e4547101a856dd5aa04"
]
},
"test1": {
"threshold": 2,
"validators": [
"0xf2561178e8ad8cadd161a855adc6eb02282b426d",
"0x28d638618aca345450604a4bb17e50ce6fe6ee0e",
"0x8dc5bd07ffd0a0053bbf4499747ba6da8442ab36"
]
},
"test2": {
"threshold": 2,
"validators": [
"0xf2561178e8ad8cadd161a855adc6eb02282b426d",
"0x28d638618aca345450604a4bb17e50ce6fe6ee0e",
"0x8dc5bd07ffd0a0053bbf4499747ba6da8442ab36"
]
},
"test3": {
"threshold": 2,
"validators": [
"0xf2561178e8ad8cadd161a855adc6eb02282b426d",
"0x28d638618aca345450604a4bb17e50ce6fe6ee0e",
"0x8dc5bd07ffd0a0053bbf4499747ba6da8442ab36"
]
}
}

@ -0,0 +1,19 @@
import { ChainMap, MultisigIsmConfig } from '@hyperlane-xyz/sdk';
export const multisigIsmConfig: ChainMap<MultisigIsmConfig> = {
// ----------- Your chains here -----------------
anvil1: {
threshold: 1,
validators: [
// Last anvil address
'0xa0ee7a142d267c1f36714e4a8f75612f20a79720',
],
},
anvil2: {
threshold: 1,
validators: [
// Last anvil address
'0xa0ee7a142d267c1f36714e4a8f75612f20a79720',
],
},
};

@ -1,119 +0,0 @@
{
"foochain": {
"id": 1174786466,
"owner": "0xfaD1C94469700833717Fa8a3017278BC1cA8031C",
"contracts": {
"testRecipient": "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e",
"create2Factory": "0x0000000000000000000000000000000000000000",
"mailbox": "0x610178dA211FEF7D417bC0e6FeD39F05609AD788",
"validatorAnnounce": "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0",
"interchainGasPaymaster": "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9",
"proxyAdmin": "0x5FbDB2315678afecb367f032d93F642f64180aa3"
}
},
"alfajores": {
"id": 44787,
"owner": "0xfaD1C94469700833717Fa8a3017278BC1cA8031C",
"contracts": {
"proxyAdmin": "0x4e4D563e2cBFC35c4BC16003685443Fae2FA702f",
"mailbox": "0xCC737a94FecaeC165AbCf12dED095BB13F037685",
"interchainGasPaymaster": "0x8f9C3888bFC8a5B25AED115A82eCbb788b196d2a",
"create2Factory": "0xc97D8e6f57b0d64971453dDc6EB8483fec9d163a",
"validatorAnnounce": "0x3Fc742696D5dc9846e04f7A1823D92cb51695f9a",
"testRecipient": "0xBC3cFeca7Df5A45d61BC60E7898E63670e1654aE"
}
},
"fuji": {
"id": 43113,
"owner": "0xfaD1C94469700833717Fa8a3017278BC1cA8031C",
"contracts": {
"proxyAdmin": "0x4e4D563e2cBFC35c4BC16003685443Fae2FA702f",
"mailbox": "0xCC737a94FecaeC165AbCf12dED095BB13F037685",
"interchainGasPaymaster": "0x8f9C3888bFC8a5B25AED115A82eCbb788b196d2a",
"create2Factory": "0xc97D8e6f57b0d64971453dDc6EB8483fec9d163a",
"validatorAnnounce": "0x3Fc742696D5dc9846e04f7A1823D92cb51695f9a",
"testRecipient": "0xBC3cFeca7Df5A45d61BC60E7898E63670e1654aE"
}
},
"mumbai": {
"id": 80001,
"owner": "0xfaD1C94469700833717Fa8a3017278BC1cA8031C",
"contracts": {
"proxyAdmin": "0x4e4D563e2cBFC35c4BC16003685443Fae2FA702f",
"mailbox": "0xCC737a94FecaeC165AbCf12dED095BB13F037685",
"interchainGasPaymaster": "0x8f9C3888bFC8a5B25AED115A82eCbb788b196d2a",
"create2Factory": "0xc97D8e6f57b0d64971453dDc6EB8483fec9d163a",
"validatorAnnounce": "0x3Fc742696D5dc9846e04f7A1823D92cb51695f9a",
"testRecipient": "0xBC3cFeca7Df5A45d61BC60E7898E63670e1654aE"
}
},
"bsctestnet": {
"id": 97,
"owner": "0xfaD1C94469700833717Fa8a3017278BC1cA8031C",
"contracts": {
"proxyAdmin": "0x4e4D563e2cBFC35c4BC16003685443Fae2FA702f",
"mailbox": "0xCC737a94FecaeC165AbCf12dED095BB13F037685",
"interchainGasPaymaster": "0x8f9C3888bFC8a5B25AED115A82eCbb788b196d2a",
"create2Factory": "0xc97D8e6f57b0d64971453dDc6EB8483fec9d163a",
"validatorAnnounce": "0x3Fc742696D5dc9846e04f7A1823D92cb51695f9a",
"testRecipient": "0xBC3cFeca7Df5A45d61BC60E7898E63670e1654aE"
}
},
"goerli": {
"id": 5,
"owner": "0xfaD1C94469700833717Fa8a3017278BC1cA8031C",
"contracts": {
"proxyAdmin": "0x4e4D563e2cBFC35c4BC16003685443Fae2FA702f",
"mailbox": "0xCC737a94FecaeC165AbCf12dED095BB13F037685",
"interchainGasPaymaster": "0x8f9C3888bFC8a5B25AED115A82eCbb788b196d2a",
"create2Factory": "0xc97D8e6f57b0d64971453dDc6EB8483fec9d163a",
"validatorAnnounce": "0x3Fc742696D5dc9846e04f7A1823D92cb51695f9a",
"testRecipient": "0xBC3cFeca7Df5A45d61BC60E7898E63670e1654aE"
}
},
"moonbasealpha": {
"id": 1287,
"owner": "0xfaD1C94469700833717Fa8a3017278BC1cA8031C",
"contracts": {
"proxyAdmin": "0x4e4D563e2cBFC35c4BC16003685443Fae2FA702f",
"mailbox": "0xCC737a94FecaeC165AbCf12dED095BB13F037685",
"interchainGasPaymaster": "0x8f9C3888bFC8a5B25AED115A82eCbb788b196d2a",
"create2Factory": "0xc97D8e6f57b0d64971453dDc6EB8483fec9d163a",
"validatorAnnounce": "0x3Fc742696D5dc9846e04f7A1823D92cb51695f9a",
"testRecipient": "0xBC3cFeca7Df5A45d61BC60E7898E63670e1654aE"
}
},
"optimismgoerli": {
"id": 420,
"owner": "0xfaD1C94469700833717Fa8a3017278BC1cA8031C",
"contracts": {
"proxyAdmin": "0x4e4D563e2cBFC35c4BC16003685443Fae2FA702f",
"mailbox": "0xCC737a94FecaeC165AbCf12dED095BB13F037685",
"interchainGasPaymaster": "0x8f9C3888bFC8a5B25AED115A82eCbb788b196d2a",
"create2Factory": "0xc97D8e6f57b0d64971453dDc6EB8483fec9d163a",
"validatorAnnounce": "0x3Fc742696D5dc9846e04f7A1823D92cb51695f9a",
"testRecipient": "0xBC3cFeca7Df5A45d61BC60E7898E63670e1654aE"
}
},
"arbitrumgoerli": {
"id": 421613,
"owner": "0xfaD1C94469700833717Fa8a3017278BC1cA8031C",
"contracts": {
"proxyAdmin": "0x4e4D563e2cBFC35c4BC16003685443Fae2FA702f",
"mailbox": "0xCC737a94FecaeC165AbCf12dED095BB13F037685",
"interchainGasPaymaster": "0x8f9C3888bFC8a5B25AED115A82eCbb788b196d2a",
"create2Factory": "0xc97D8e6f57b0d64971453dDc6EB8483fec9d163a",
"validatorAnnounce": "0x3Fc742696D5dc9846e04f7A1823D92cb51695f9a",
"testRecipient": "0xBC3cFeca7Df5A45d61BC60E7898E63670e1654aE"
}
},
"test1": {
"id": 13371
},
"test2": {
"id": 13372
},
"test3": {
"id": 13373
}
}

@ -0,0 +1,24 @@
import { ChainMap } from '@hyperlane-xyz/sdk';
export const startBlocks: ChainMap<number> = {
// --------------- Mainnets ---------------------
celo: 16884144,
ethereum: 16271503,
avalanche: 24145479,
polygon: 37313389,
bsc: 25063295,
arbitrum: 49073182,
optimism: 55698988,
moonbeam: 2595747,
gnosis: 25900000,
// --------------- Testnets ---------------------
alfajores: 14863532,
fuji: 16330615,
mumbai: 29390033,
bsctestnet: 25001629,
goerli: 8039005,
sepolia: 3082913,
moonbasealpha: 3310405,
optimismgoerli: 3055263,
arbitrumgoerli: 1941997,
};

@ -1,14 +0,0 @@
[profile.default]
src = 'scripts'
out = 'out'
libs = ['node_modules', 'lib']
test = 'test'
cache_path = 'forge-cache'
allow_paths = ["../node_modules"]
solc = '0.8.17'
optimizer = true
optimizer_runs = 999_999
fs_permissions = [{ access = "read-write", path = "./"}]
[profile.ci]
verbosity = 4

@ -1,80 +0,0 @@
// from https://gist.github.com/rmeissner/76d6345796909ee41fb9f36fdaa4d15f
pragma solidity >=0.8.0 <0.9.0;
library BytesLib {
function slice(
bytes memory _bytes,
uint256 _start,
uint256 _length
) internal pure returns (bytes memory) {
require(_length + 31 >= _length, "slice_overflow");
require(_bytes.length >= _start + _length, "slice_outOfBounds");
bytes memory tempBytes;
// Check length is 0. `iszero` return 1 for `true` and 0 for `false`.
assembly {
switch iszero(_length)
case 0 {
// Get a location of some free memory and store it in tempBytes as
// Solidity does for memory variables.
tempBytes := mload(0x40)
// Calculate length mod 32 to handle slices that are not a multiple of 32 in size.
let lengthmod := and(_length, 31)
// tempBytes will have the following format in memory: <length><data>
// When copying data we will offset the start forward to avoid allocating additional memory
// Therefore part of the length area will be written, but this will be overwritten later anyways.
// In case no offset is require, the start is set to the data region (0x20 from the tempBytes)
// mc will be used to keep track where to copy the data to.
let mc := add(
add(tempBytes, lengthmod),
mul(0x20, iszero(lengthmod))
)
let end := add(mc, _length)
for {
// Same logic as for mc is applied and additionally the start offset specified for the method is added
let cc := add(
add(
add(_bytes, lengthmod),
mul(0x20, iszero(lengthmod))
),
_start
)
} lt(mc, end) {
// increase `mc` and `cc` to read the next word from memory
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} {
// Copy the data from source (cc location) to the slice data (mc location)
mstore(mc, mload(cc))
}
// Store the length of the slice. This will overwrite any partial data that
// was copied when having slices that are not a multiple of 32.
mstore(tempBytes, _length)
// update free-memory pointer
// allocating the array padded to 32 bytes like the compiler does now
// To set the used memory as a multiple of 32, add 31 to the actual memory usage (mc)
// and remove the modulo 32 (the `and` with `not(31)`)
mstore(0x40, and(add(mc, 31), not(31)))
}
// if we want a zero-length slice let's just return a zero-length array
default {
tempBytes := mload(0x40)
// zero out the 32 bytes slice we are about to return
// we need to do it because Solidity does not garbage collect
mstore(tempBytes, 0)
// update free-memory pointer
// tempBytes uses 32 bytes in memory (even when empty) for the length.
mstore(0x40, add(tempBytes, 0x20))
}
}
return tempBytes;
}
}

@ -1,105 +0,0 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;
import "../lib/forge-std/src/console.sol";
import {ConfigLib} from "../lib/ConfigLib.sol";
import {MultisigIsm} from "@hyperlane-xyz/core/contracts/isms/MultisigIsm.sol";
import {TransparentUpgradeableProxy} from "@hyperlane-xyz/core/contracts/upgrade/TransparentUpgradeableProxy.sol";
library CheckLib {
function check(
ConfigLib.HyperlaneDomainConfig memory config,
ConfigLib.MultisigIsmConfig memory ismConfig
) internal view {
checkOwners(config);
checkAdmins(config);
checkMailboxIsm(config, ismConfig);
console.log(
"Succesfully checked Hyperlane deployment for %s",
config.chainName
);
}
function checkOwners(
ConfigLib.HyperlaneDomainConfig memory config
) private view {
require(
config.admin.owner() == config.owner,
"ProxyAdmin owner misconfigured"
);
require(
config.igp.owner() == config.owner,
"InterchainGasPaymaster owner misconfigured"
);
require(
config.mailbox.owner() == config.owner,
"Mailbox owner misconfigured"
);
}
function checkAdmins(
ConfigLib.HyperlaneDomainConfig memory config
) private view {
require(
config.admin.getProxyAdmin(
TransparentUpgradeableProxy(payable(address(config.igp)))
) == address(config.admin),
"InterchainGasPaymaster proxy admin misconfigured"
);
require(
config.admin.getProxyAdmin(
TransparentUpgradeableProxy(payable(address(config.mailbox)))
) == address(config.admin),
"Mailbox proxy admin misconfigured"
);
}
function checkMailboxIsm(
ConfigLib.HyperlaneDomainConfig memory config,
ConfigLib.MultisigIsmConfig memory ismConfig
) private view {
MultisigIsm ism = MultisigIsm(address(config.mailbox.defaultIsm()));
check(ismConfig, ism, config.owner);
}
function contains(
address[] memory set,
address element
) internal pure returns (bool) {
for (uint256 i = 0; i < set.length; i++) {
if (set[i] == element) {
return true;
}
}
return false;
}
function check(
ConfigLib.MultisigIsmConfig memory config,
MultisigIsm ism,
address owner
) internal view {
require(ism.owner() == owner, "MultisigIsm owner misconfigured");
for (uint256 i = 0; i < config.domains.length; i++) {
ConfigLib.MultisigIsmDomainConfig memory domain = config.domains[i];
require(
domain.threshold == ism.threshold(domain.domainId),
string.concat(
"Default MultisigIsm threshold misconfigured for",
domain.chainName
)
);
address[] memory validators = ism.validators(domain.domainId);
require(domain.validators.length == validators.length);
for (uint256 j = 0; j < validators.length; j++) {
require(
contains(domain.validators, validators[j]),
string.concat(
"Default MultisigIsm validator set misconfigured for ",
domain.chainName
)
);
}
}
}
}

@ -1,247 +0,0 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;
import "../lib/forge-std/src/Script.sol";
import {Vm} from "../lib/forge-std/src/Vm.sol";
import {BytesLib} from "../lib/BytesLib.sol";
import {MultisigIsm} from "@hyperlane-xyz/core/contracts/isms/MultisigIsm.sol";
import {Mailbox} from "@hyperlane-xyz/core/contracts/Mailbox.sol";
import {InterchainGasPaymaster} from "@hyperlane-xyz/core/contracts/igps/InterchainGasPaymaster.sol";
import {ValidatorAnnounce} from "@hyperlane-xyz/core/contracts/ValidatorAnnounce.sol";
import {ProxyAdmin} from "@hyperlane-xyz/core/contracts/upgrade/ProxyAdmin.sol";
import {TransparentUpgradeableProxy} from "@hyperlane-xyz/core/contracts/upgrade/TransparentUpgradeableProxy.sol";
import {Create2Factory} from "@hyperlane-xyz/core/contracts/Create2Factory.sol";
import {TestRecipient} from "@hyperlane-xyz/core/contracts/test/TestRecipient.sol";
library ConfigLib {
using stdJson for string;
using BytesLib for bytes;
struct HyperlaneDomainConfig {
string chainName;
uint32 domainId;
address owner;
Mailbox mailbox;
InterchainGasPaymaster igp;
ProxyAdmin admin;
Create2Factory create2;
ValidatorAnnounce validatorAnnounce;
TestRecipient testRecipient;
}
struct MultisigIsmDomainConfig {
string chainName;
uint32 domainId;
uint8 threshold;
address[] validators;
}
struct MultisigIsmConfig {
MultisigIsmDomainConfig[] domains;
}
function readContractAddress(
Vm vm,
string memory chainName,
string memory contractName
) private view returns (address) {
string memory json = vm.readFile("config/networks.json");
string memory prefix = ".contracts.";
try
vm.parseJson(
json,
string.concat(
".",
chainName,
string.concat(prefix, contractName)
)
)
returns (bytes memory result) {
address parsedAddr = abi.decode(result, (address));
return parsedAddr == address(0x20) ? address(0) : parsedAddr;
} catch {
return address(0);
}
}
function readHyperlaneDomainConfig(
Vm vm,
string memory chainName
) internal view returns (HyperlaneDomainConfig memory) {
string memory json = vm.readFile("config/networks.json");
// console.log(json);
uint32 domainId = abi.decode(
vm.parseJson(json, string.concat(".", chainName, ".id")),
(uint32)
);
address owner = abi.decode(
vm.parseJson(json, string.concat(".", chainName, ".owner")),
(address)
);
Mailbox mailbox = Mailbox(
readContractAddress(vm, chainName, "mailbox")
);
InterchainGasPaymaster igp = InterchainGasPaymaster(
readContractAddress(vm, chainName, "interchainGasPaymaster")
);
ProxyAdmin admin = ProxyAdmin(
readContractAddress(vm, chainName, "proxyAdmin")
);
Create2Factory create2 = Create2Factory(
readContractAddress(vm, chainName, "create2Factory")
);
TestRecipient recipient = TestRecipient(
readContractAddress(vm, chainName, "testRecipient")
);
ValidatorAnnounce validatorAnnounce = ValidatorAnnounce(
readContractAddress(vm, chainName, "validatorAnnounce")
);
return
HyperlaneDomainConfig(
chainName,
domainId,
owner,
mailbox,
igp,
admin,
create2,
validatorAnnounce,
recipient
);
}
function readMultisigIsmDomainConfig(
Vm vm,
string memory chainName
) private view returns (MultisigIsmDomainConfig memory) {
console.log(chainName);
string memory json = vm.readFile("config/multisig_ism.json");
uint8 threshold = abi.decode(
vm.parseJson(json, string.concat(".", chainName, ".threshold")),
(uint8)
);
address[] memory validators = abi.decode(
vm.parseJson(json, string.concat(".", chainName, ".validators")),
(address[])
);
json = vm.readFile("config/networks.json");
uint32 domainId = abi.decode(
vm.parseJson(json, string.concat(".", chainName, ".id")),
(uint32)
);
return
MultisigIsmDomainConfig(chainName, domainId, threshold, validators);
}
function readMultisigIsmConfig(
Vm vm,
string[] memory chainNames
) internal view returns (MultisigIsmConfig memory) {
MultisigIsmDomainConfig[]
memory domains = new MultisigIsmDomainConfig[](chainNames.length);
for (uint256 i = 0; i < chainNames.length; i++) {
string memory chainName = chainNames[i];
domains[i] = readMultisigIsmDomainConfig(vm, chainName);
}
return MultisigIsmConfig(domains);
}
function writeAgentConfig(
HyperlaneDomainConfig memory config,
Vm vm,
uint256 startBlock
) internal {
string memory baseConfig = "config";
vm.serializeString(
baseConfig,
"domain",
vm.toString(uint256(config.domainId))
);
vm.serializeString(baseConfig, "rpcStyle", "ethereum");
vm.serializeString(baseConfig, "finalityBlocks", "POPULATE_ME");
string memory addresses = "addresses";
vm.serializeAddress(addresses, "mailbox", address(config.mailbox));
vm.serializeAddress(
addresses,
"validatorAnnounce",
address(config.validatorAnnounce)
);
vm.serializeString(
baseConfig,
"addresses",
vm.serializeAddress(
addresses,
"interchainGasPaymaster",
address(config.igp)
)
);
string memory connection = "connection";
vm.serializeString(connection, "type", "http");
vm.serializeString(
baseConfig,
"connection",
vm.serializeString(connection, "url", "")
);
string memory index = "index";
vm.serializeString(
baseConfig,
"index",
vm.serializeString(index, "from", vm.toString(startBlock))
);
vm.serializeString(baseConfig, "name", config.chainName);
vm
.serializeString(
"topLevel",
"chains",
vm.serializeString(
"chainLevel",
config.chainName,
vm.serializeString(baseConfig, "protocol", "ethereum")
)
)
.write(
string.concat(
"./config/",
config.chainName,
"_agent_config.json"
)
);
}
function write(HyperlaneDomainConfig memory config, Vm vm) internal {
string memory contracts = "contracts";
vm.serializeAddress(contracts, "mailbox", address(config.mailbox));
vm.serializeAddress(
contracts,
"interchainGasPaymaster",
address(config.igp)
);
vm.serializeAddress(contracts, "proxyAdmin", address(config.admin));
vm.serializeAddress(
contracts,
"validatorAnnounce",
address(config.validatorAnnounce)
);
vm.serializeAddress(
contracts,
"testRecipient",
address(config.testRecipient)
);
vm
.serializeAddress(
contracts,
"create2Factory",
address(config.create2)
)
.write(
"./config/networks.json",
string.concat(".", config.chainName, ".contracts")
);
}
}

@ -1,165 +0,0 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;
import "../lib/forge-std/src/console.sol";
import {ConfigLib} from "../lib/ConfigLib.sol";
import {MultisigIsm} from "@hyperlane-xyz/core/contracts/isms/MultisigIsm.sol";
import {Mailbox} from "@hyperlane-xyz/core/contracts/Mailbox.sol";
import {InterchainGasPaymaster} from "@hyperlane-xyz/core/contracts/igps/InterchainGasPaymaster.sol";
import {ValidatorAnnounce} from "@hyperlane-xyz/core/contracts/ValidatorAnnounce.sol";
import {ProxyAdmin} from "@hyperlane-xyz/core/contracts/upgrade/ProxyAdmin.sol";
import {TransparentUpgradeableProxy} from "@hyperlane-xyz/core/contracts/upgrade/TransparentUpgradeableProxy.sol";
import {Create2Factory} from "@hyperlane-xyz/core/contracts/Create2Factory.sol";
import {TestRecipient} from "@hyperlane-xyz/core/contracts/test/TestRecipient.sol";
library DeployLib {
function deploy(
ConfigLib.HyperlaneDomainConfig memory config,
ConfigLib.MultisigIsmConfig memory ismConfig
) internal {
deployProxyAdmin(config);
deployIgp(config);
deployMailbox(config, ismConfig);
deployTestRecipient(config);
deployValidatorAnnounce(config);
}
function deployValidatorAnnounce(
ConfigLib.HyperlaneDomainConfig memory config
) private {
if (address(config.validatorAnnounce) == address(0)) {
config.validatorAnnounce = new ValidatorAnnounce(
address(config.mailbox)
);
console.log(
"ValidatorAnnounce deployed at address %s",
address(config.validatorAnnounce)
);
} else {
console.log(
"Found ValidatorAnnounce at address %s, skipping deployment",
address(config.validatorAnnounce)
);
}
}
function deployProxyAdmin(
ConfigLib.HyperlaneDomainConfig memory config
) private {
if (address(config.admin) == address(0)) {
config.admin = new ProxyAdmin();
console.log(
"ProxyAdmin deployed at address %s",
address(config.admin)
);
config.admin.transferOwnership(config.owner);
} else {
console.log(
"Found ProxyAdmin at address %s, skipping deployment",
address(config.admin)
);
}
}
function deployIgp(ConfigLib.HyperlaneDomainConfig memory config) private {
require(
address(config.admin) != address(0),
"Must deploy ProxyAdmin before InterchainGasPaymaster"
);
if (address(config.igp) == address(0)) {
InterchainGasPaymaster impl = new InterchainGasPaymaster();
bytes memory initData = abi.encodeCall(
InterchainGasPaymaster.initialize,
()
);
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
address(impl),
address(config.admin),
initData
);
console.log(
"InterchainGasPaymaster deployed at address %s",
address(proxy)
);
config.igp = InterchainGasPaymaster(address(proxy));
config.igp.transferOwnership(config.owner);
} else {
console.log(
"Found InterchainGasPaymaster at address %s, skipping deployment",
address(config.igp)
);
}
}
function deployMailbox(
ConfigLib.HyperlaneDomainConfig memory config,
ConfigLib.MultisigIsmConfig memory ismConfig
) private {
require(
address(config.admin) != address(0),
"Must deploy ProxyAdmin before Mailbox"
);
if (address(config.mailbox) == address(0)) {
MultisigIsm ism = deploy(ismConfig, config.owner);
Mailbox mailbox = new Mailbox(config.domainId);
bytes memory initData = abi.encodeCall(
Mailbox.initialize,
(config.owner, address(ism))
);
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
address(mailbox),
address(config.admin),
initData
);
console.log("Mailbox deployed at address %s", address(proxy));
config.mailbox = Mailbox(address(proxy));
} else {
console.log(
"Found Mailbox at address %s, skipping deployment",
address(config.igp)
);
}
}
function deployTestRecipient(
ConfigLib.HyperlaneDomainConfig memory config
) private {
if (address(config.testRecipient) == address(0)) {
config.testRecipient = new TestRecipient();
console.log(
"TestRecipient deployed at address %s",
address(config.testRecipient)
);
} else {
console.log(
"Found TestRecipient at address %s, skipping deployment",
address(config.igp)
);
}
}
function deploy(
ConfigLib.MultisigIsmConfig memory config,
address owner
) internal returns (MultisigIsm) {
// Deploy a default MultisigIsm and enroll validators for remote
// networks.
MultisigIsm ism = new MultisigIsm();
console.log("MultisigIsm deployed at address %s", address(ism));
uint32[] memory remoteDomainIds = new uint32[](config.domains.length);
uint8[] memory remoteThresholds = new uint8[](config.domains.length);
address[][] memory remoteValidators = new address[][](
config.domains.length
);
for (uint256 i = 0; i < config.domains.length; i++) {
remoteDomainIds[i] = config.domains[i].domainId;
remoteThresholds[i] = config.domains[i].threshold;
remoteValidators[i] = config.domains[i].validators;
}
ism.enrollValidators(remoteDomainIds, remoteValidators);
ism.setThresholds(remoteDomainIds, remoteThresholds);
ism.transferOwnership(owner);
return ism;
}
}

@ -1 +0,0 @@
Subproject commit 181c0c686a8421cfb530e06bda9d00632c9d8637

@ -7,11 +7,25 @@
"author": "asa@hyperlane.xyz",
"license": "Apache 2.0",
"scripts": {
"prettier": "prettier --write ./scripts ./lib"
"build": "tsc",
"prettier": "prettier --write ./config ./scripts ./src"
},
"dependencies": {
"@hyperlane-xyz/core": "1.1.2",
"@hyperlane-xyz/core": "1.3.0",
"@hyperlane-xyz/sdk": "^1.3.0",
"@hyperlane-xyz/utils": "^1.3.0",
"@types/node": "^18.14.5",
"@types/yargs": "^17.0.22",
"ethers": "^5.7.2",
"prettier": "^2.8.2",
"prettier-plugin-solidity": "^1.1.1"
"prettier-plugin-solidity": "^1.1.1",
"ts-node": "^10.9.1",
"typescript": "^4.9.5",
"yargs": "^17.7.1"
},
"packageManager": "yarn@1.22.19",
"devDependencies": {
"@types/coingecko-api": "^1.0.10",
"@types/debug": "^4.1.7"
}
}

@ -1,42 +0,0 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;
import "../lib/forge-std/src/Script.sol";
import "../lib/forge-std/src/console.sol";
import {BytesLib} from "../lib/BytesLib.sol";
import {ConfigLib} from "../lib/ConfigLib.sol";
import {Mailbox} from "@hyperlane-xyz/core/contracts/Mailbox.sol";
import {TypeCasts} from "@hyperlane-xyz/core/contracts/libs/TypeCasts.sol";
// TODO: Maybe take recipient as an arg..
contract CheckMessage is Script {
using TypeCasts for address;
using BytesLib for bytes;
function run() public view {
string memory destination = vm.envString("DESTINATION");
bytes32 messageId = vm.envBytes32("MESSAGE_ID");
Mailbox mailbox = ConfigLib
.readHyperlaneDomainConfig(vm, destination)
.mailbox;
bool delivered = mailbox.delivered(messageId);
if (delivered) {
console.log(
"Message ID '%s' HAS been delivered to %s",
vm.toString(messageId),
destination
);
} else {
console.log(
"Message ID '%s' HAS NOT been delivered to %s",
vm.toString(messageId),
destination
);
}
console.log(
"https://explorer.hyperlane.xyz/message/%s",
string(abi.encodePacked(vm.toString(messageId)).slice(2, 64))
);
}
}

@ -1,35 +0,0 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;
import "../lib/forge-std/src/Script.sol";
import {ConfigLib} from "../lib/ConfigLib.sol";
import {CheckLib} from "../lib/CheckLib.sol";
import {DeployLib} from "../lib/DeployLib.sol";
contract DeployCore is Script {
using ConfigLib for ConfigLib.HyperlaneDomainConfig;
using CheckLib for ConfigLib.HyperlaneDomainConfig;
using DeployLib for ConfigLib.HyperlaneDomainConfig;
function run() public {
string memory local = vm.envString("LOCAL");
string[] memory remotes = vm.envString("REMOTES", ",");
ConfigLib.HyperlaneDomainConfig memory config = ConfigLib
.readHyperlaneDomainConfig(vm, local);
ConfigLib.MultisigIsmConfig memory ismConfig = ConfigLib
.readMultisigIsmConfig(vm, remotes);
vm.startBroadcast();
uint256 startBlock = block.number;
config.deploy(ismConfig);
config.check(ismConfig);
// Write the output to disk
config.write(vm);
config.writeAgentConfig(vm, startBlock);
vm.stopBroadcast();
}
}

@ -1,39 +0,0 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;
import "../lib/forge-std/src/Script.sol";
import "../lib/forge-std/src/console.sol";
import {ConfigLib} from "../lib/ConfigLib.sol";
import {CheckLib} from "../lib/CheckLib.sol";
import {DeployLib} from "../lib/DeployLib.sol";
import {MultisigIsm} from "@hyperlane-xyz/core/contracts/isms/MultisigIsm.sol";
import {TestRecipient} from "@hyperlane-xyz/core/contracts/test/TestRecipient.sol";
import {InterchainGasPaymaster} from "@hyperlane-xyz/core/contracts/igps/InterchainGasPaymaster.sol";
// TODO: Deploy test recipient, maybe write to networks.
contract DeployMultisigIsm is Script {
using CheckLib for ConfigLib.MultisigIsmConfig;
using DeployLib for ConfigLib.MultisigIsmConfig;
function run() public {
address owner = vm.envAddress("OWNER");
string[] memory remotes = vm.envString("REMOTES", ",");
ConfigLib.MultisigIsmConfig memory config = ConfigLib
.readMultisigIsmConfig(vm, remotes);
vm.startBroadcast();
MultisigIsm ism = config.deploy(owner);
TestRecipient recipient = new TestRecipient();
recipient.setInterchainSecurityModule(address(ism));
console.log("TestRecipient deployed at address %s", address(recipient));
InterchainGasPaymaster igp = new InterchainGasPaymaster();
console.log(
"InterchainGasPaymaster deployed at address %s",
address(igp)
);
config.check(ism, owner);
}
}

@ -1,44 +0,0 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;
import "../lib/forge-std/src/Script.sol";
import "../lib/forge-std/src/console.sol";
import {BytesLib} from "../lib/BytesLib.sol";
import {ConfigLib} from "../lib/ConfigLib.sol";
import {Mailbox} from "@hyperlane-xyz/core/contracts/Mailbox.sol";
import {TypeCasts} from "@hyperlane-xyz/core/contracts/libs/TypeCasts.sol";
contract SendTestMessage is Script {
using TypeCasts for address;
using BytesLib for bytes;
function run() public {
string memory origin = vm.envString("ORIGIN");
string memory destination = vm.envString("DESTINATION");
address recipient = vm.envAddress("RECIPIENT");
string memory body = vm.envString("BODY");
Mailbox mailbox = ConfigLib
.readHyperlaneDomainConfig(vm, origin)
.mailbox;
ConfigLib.HyperlaneDomainConfig memory config = ConfigLib
.readHyperlaneDomainConfig(vm, destination);
vm.startBroadcast();
bytes32 messageId = mailbox.dispatch(
config.domainId,
address(recipient).addressToBytes32(),
abi.encode(body)
);
console.log(
"Sent message with ID %s from %s to %s",
vm.toString(messageId),
origin,
destination
);
console.log(
"https://explorer.hyperlane.xyz/message/%s",
string(abi.encodePacked(vm.toString(messageId)).slice(2, 64))
);
}
}

@ -0,0 +1,18 @@
import { HyperlanePermissionlessDeployer } from '../src/deployer';
async function main() {
const deployer = await HyperlanePermissionlessDeployer.fromArgs();
try {
await deployer.deploy();
} catch (e) {
console.error(`Encountered error during deploy`);
console.error(e);
}
}
main()
.then(() => console.info('Deploy completed successfully'))
.catch((e) => {
console.error(e);
process.exit(1);
});

@ -0,0 +1,167 @@
import {
CoreFactories,
coreFactories,
DispatchedMessage,
HyperlaneAddressesMap,
HyperlaneApp,
HyperlaneCore,
HyperlaneIgp,
MultiProvider,
} from '@hyperlane-xyz/sdk';
import {
igpFactories,
IgpFactories,
} from '@hyperlane-xyz/sdk/dist/gas/contracts';
import { utils } from '@hyperlane-xyz/utils';
import { sleep } from '@hyperlane-xyz/utils/dist/src/utils';
import { ethers } from 'ethers';
import yargs from 'yargs';
import {
assertBalances,
assertBytes32,
getMultiProvider,
mergedContractAddresses,
} from '../src/config';
export function getArgs(multiProvider: MultiProvider) {
// Only accept chains for which we have both a connection and contract addresses
const { intersection } = multiProvider.intersect(
Object.keys(mergedContractAddresses),
);
return yargs(process.argv.slice(2))
.describe('chains', 'chain to send message from')
.choices('chains', intersection)
.demandOption('chains')
.array('chains')
.describe('key', 'hexadecimal private key for transaction signing')
.string('key')
.coerce('key', assertBytes32)
.demandOption('key')
.describe('timeout', 'timeout in seconds')
.number('timeout')
.default('timeout', 10 * 60)
.middleware(assertBalances(multiProvider, (argv) => argv.chains)).argv;
}
function coreFromAddressesMap(
addressesMap: HyperlaneAddressesMap<CoreFactories>,
_multiProvider: MultiProvider,
): HyperlaneCore {
const { contractsMap, multiProvider } = HyperlaneApp.fromAddressesMap(
addressesMap,
coreFactories,
_multiProvider,
);
return new HyperlaneCore(contractsMap, multiProvider);
}
function igpFromAddressesMap(
addressesMap: HyperlaneAddressesMap<IgpFactories>,
_multiProvider: MultiProvider,
): HyperlaneIgp {
const { contractsMap, multiProvider } = HyperlaneApp.fromAddressesMap(
addressesMap,
igpFactories,
_multiProvider,
);
return new HyperlaneIgp(contractsMap, multiProvider);
}
async function main() {
let timedOut = false;
const multiProvider = getMultiProvider();
let { chains, key, timeout } = await getArgs(multiProvider);
const timeoutId = setTimeout(() => {
timedOut = true;
}, timeout * 1000);
const signer = new ethers.Wallet(key);
multiProvider.setSharedSigner(signer);
const core = coreFromAddressesMap(mergedContractAddresses, multiProvider);
const igp = igpFromAddressesMap(mergedContractAddresses, multiProvider);
const messages: Set<DispatchedMessage> = new Set();
for (const origin of chains) {
const mailbox = core.getContracts(origin).mailbox;
const defaultIgp =
igp.getContracts(origin).defaultIsmInterchainGasPaymaster;
for (const destination of chains) {
const destinationDomain = multiProvider.getDomainId(destination);
if (origin === destination) continue;
try {
const recipient = mergedContractAddresses[destination]
.testRecipient as string;
if (!recipient) {
throw new Error(`Unable to find TestRecipient for ${destination}`);
}
const messageTx = await mailbox.dispatch(
destinationDomain,
utils.addressToBytes32(recipient),
'0xdeadbeef',
);
const messageReceipt = await multiProvider.handleTx(origin, messageTx);
const dispatchedMessages = core.getDispatchedMessages(messageReceipt);
if (dispatchedMessages.length !== 1) continue;
const dispatchedMessage = dispatchedMessages[0];
console.log(
`Sent message from ${origin} to ${recipient} on ${destination} with message ID ${dispatchedMessage.id}`,
);
// Make gas payment...
const gasAmount = 100_000;
const value = await defaultIgp.quoteGasPayment(
destinationDomain,
gasAmount,
);
const paymentTx = await defaultIgp.payForGas(
dispatchedMessage.id,
destinationDomain,
gasAmount,
await multiProvider.getSignerAddress(origin),
{ value },
);
await paymentTx.wait();
messages.add(dispatchedMessage);
} catch (e) {
console.error(
`Encountered error sending message from ${origin} to ${destination}`,
);
console.error(e);
}
}
}
while (messages.size > 0 && !timedOut) {
for (const message of messages.values()) {
const origin = multiProvider.getChainName(message.parsed.origin);
const destination = multiProvider.getChainName(
message.parsed.destination,
);
const mailbox = core.getContracts(destination).mailbox;
const delivered = await mailbox.delivered(message.id);
if (delivered) {
messages.delete(message);
console.log(
`Message from ${origin} to ${destination} with ID ${
message!.id
} was delivered`,
);
} else {
console.log(
`Message from ${origin} to ${destination} with ID ${
message!.id
} has not yet been delivered`,
);
}
await sleep(5000);
}
}
clearTimeout(timeoutId);
if (timedOut) {
console.error('Timed out waiting for messages to be delivered');
process.exit(1);
}
}
main()
.then(() => console.info('Testing complete'))
.catch((e) => {
console.error(e);
process.exit(1);
});

@ -0,0 +1,53 @@
import { TestRecipient, TestRecipient__factory } from '@hyperlane-xyz/core';
import {
ChainMap,
ChainName,
HyperlaneDeployer,
MultiProvider,
} from '@hyperlane-xyz/sdk';
import { types } from '@hyperlane-xyz/utils';
import debug from 'debug';
// Maps chain name to ISM address
export type TestRecipientConfig = {
ism: types.Address;
};
export type TestRecipientContracts = {
testRecipient: TestRecipient;
};
export type TestRecipientAddresses = {
testRecipient: types.Address;
};
export const testRecipientFactories = {
testRecipient: new TestRecipient__factory(),
};
export class HyperlaneTestRecipientDeployer extends HyperlaneDeployer<
TestRecipientConfig,
typeof testRecipientFactories
> {
constructor(
multiProvider: MultiProvider,
configMap: ChainMap<TestRecipientConfig>,
factoriesOverride = testRecipientFactories,
) {
super(multiProvider, configMap, factoriesOverride, {
logger: debug('hyperlane:TestRecipientDeployer'),
});
}
async deployContracts(
chain: ChainName,
config: TestRecipientConfig,
): Promise<TestRecipientContracts> {
const testRecipient = await this.deployContract(chain, 'testRecipient', []);
const tx = testRecipient.setInterchainSecurityModule(config.ism);
await this.multiProvider.handleTx(chain, tx);
return {
testRecipient,
};
}
}

@ -0,0 +1,159 @@
import {
buildAgentConfig,
ChainMap,
ChainName,
CoreConfig,
defaultMultisigIsmConfigs,
GasOracleContractType,
HyperlaneAddressesMap,
HyperlaneAgentAddresses,
MultiProvider,
MultisigIsmConfig,
multisigIsmVerificationCost,
objFilter,
objMerge,
OverheadIgpConfig,
} from '@hyperlane-xyz/sdk';
import { hyperlaneEnvironments } from '@hyperlane-xyz/sdk/dist/consts/environments';
import { types, utils } from '@hyperlane-xyz/utils';
import { ethers } from 'ethers';
import artifactAddresses from '../artifacts/addresses.json';
import { chains } from '../config/chains';
import { multisigIsmConfig } from '../config/multisig_ism';
import { readJSON } from './json';
export function getMultiProvider() {
const multiProvider = new MultiProvider();
for (const metadata of Object.values(chains)) {
multiProvider.addChain(metadata);
}
return multiProvider;
}
export function assertBytes32(value: string): string {
if (
ethers.utils.isHexString(value) &&
ethers.utils.hexDataLength(value) == 32
) {
return value;
}
throw new Error(`Invalid value ${value}, must be a 32 byte hex string`);
}
export function assertBalances(
multiProvider: MultiProvider,
chainsFunc: (argv: any) => ChainName[],
): (argv: any) => Promise<void> {
return async (argv: any) => {
const chains = chainsFunc(argv);
const signer = new ethers.Wallet(argv.key);
const address = await signer.getAddress();
Promise.all(
chains.map(async (chain: ChainName) => {
const balance = await multiProvider
.getProvider(chain)
.getBalance(address);
if (balance.isZero())
throw new Error(`${address} has no balance on ${chain}`);
}),
);
};
}
export function coerceAddressToBytes32(value: string): string {
if (ethers.utils.isHexString(value)) {
const length = ethers.utils.hexDataLength(value);
if (length == 32) {
return value;
} else if (length == 20) {
return utils.addressToBytes32(value);
}
}
throw new Error(`Invalid value ${value}, must be a 20 or 32 byte hex string`);
}
export function buildCoreConfig(
owner: types.Address,
chains: ChainName[],
): ChainMap<CoreConfig> {
const configMap: ChainMap<CoreConfig> = {};
for (const local of chains) {
const multisigIsmConfigs: ChainMap<MultisigIsmConfig> = {};
const mergedMultisigIsmConfig: ChainMap<MultisigIsmConfig> = objMerge(
defaultMultisigIsmConfigs,
multisigIsmConfig,
);
for (const remote of chains) {
if (local === remote) continue;
multisigIsmConfigs[remote] = mergedMultisigIsmConfig[remote];
}
configMap[local] = {
owner,
multisigIsm: multisigIsmConfigs,
};
}
return configMap;
}
export function buildIgpConfig(
owner: types.Address,
chains: ChainName[],
): ChainMap<OverheadIgpConfig> {
const configMap: ChainMap<OverheadIgpConfig> = {};
for (const local of chains) {
const overhead: ChainMap<number> = {};
const gasOracleType: ChainMap<GasOracleContractType> = {};
for (const remote of chains) {
if (local === remote) continue;
overhead[remote] = multisigIsmVerificationCost(
multisigIsmConfig[remote].threshold,
multisigIsmConfig[remote].validators.length,
);
gasOracleType[remote] = GasOracleContractType.StorageGasOracle;
}
configMap[local] = {
owner,
beneficiary: owner,
gasOracleType,
overhead,
};
}
return configMap;
}
export const sdkContractAddresses = {
...hyperlaneEnvironments.testnet,
...hyperlaneEnvironments.mainnet,
};
export const mergedContractAddresses = objMerge(
sdkContractAddresses,
artifactAddresses,
);
export function buildOverriddenAgentConfig(
chains: ChainName[],
multiProvider: MultiProvider,
startBlocks: ChainMap<number>,
) {
const localAddresses = readJSON('./artifacts', 'addresses.json');
const mergedAddresses: HyperlaneAddressesMap<any> = objMerge(
sdkContractAddresses,
localAddresses,
);
const filteredAddresses: ChainMap<HyperlaneAgentAddresses> = objFilter(
mergedAddresses,
(chain, v): v is HyperlaneAgentAddresses =>
chains.includes(chain) &&
!!v.mailbox &&
!!v.interchainGasPaymaster &&
!!v.validatorAnnounce,
);
return buildAgentConfig(
chains,
multiProvider,
filteredAddresses,
startBlocks,
);
}

@ -0,0 +1,172 @@
import {
ChainMap,
ChainName,
CoreFactories,
HyperlaneContractsMap,
HyperlaneCoreDeployer,
HyperlaneIgpDeployer,
MultiProvider,
objMap,
objMerge,
serializeContractsMap,
} from '@hyperlane-xyz/sdk';
import yargs from 'yargs';
import { LegacyMultisigIsm } from '@hyperlane-xyz/core';
import { ethers } from 'ethers';
import { multisigIsmConfig } from '../config/multisig_ism';
import { startBlocks } from '../config/start_blocks';
import {
assertBalances,
assertBytes32,
buildCoreConfig,
buildIgpConfig,
buildOverriddenAgentConfig,
getMultiProvider,
} from './config';
import { mergeJSON, writeJSON } from './json';
import {
HyperlaneTestRecipientDeployer,
TestRecipientConfig,
} from './TestRecipientDeployer';
export function getArgs(multiProvider: MultiProvider) {
// For each chain, we need:
// - ChainMetadata for the MultiProvider
// - A MultisigIsmConfig
const { intersection } = multiProvider.intersect(
Object.keys(multisigIsmConfig),
);
return yargs(process.argv.slice(2))
.describe('local', 'The chain to deploy to')
.choices('local', intersection)
.demandOption('local')
.array('remotes')
.describe(
'remotes',
"The chains with which 'local' will be able to send and receive messages",
)
.choices('remotes', intersection)
.demandOption('remotes')
.describe('key', 'A hexadecimal private key for transaction signing')
.string('key')
.coerce('key', assertBytes32)
.demandOption('key')
.middleware(
assertBalances(multiProvider, (argv) => argv.remotes.concat(argv.local)),
)
.describe('write-agent-config', 'Whether or not to write agent config')
.default('write-agent-config', true)
.boolean('write-agent-config').argv;
}
type MultisigIsmContracts = {
multisigIsm: LegacyMultisigIsm;
};
export class HyperlanePermissionlessDeployer {
constructor(
public readonly multiProvider: MultiProvider,
public readonly signer: ethers.Signer,
public readonly local: ChainName,
public readonly remotes: ChainName[],
public readonly writeAgentConfig?: boolean,
) {}
static async fromArgs(): Promise<HyperlanePermissionlessDeployer> {
const multiProvider = getMultiProvider();
const { local, remotes, key, writeAgentConfig } = await getArgs(
multiProvider,
);
const signer = new ethers.Wallet(key);
multiProvider.setSharedSigner(signer);
return new HyperlanePermissionlessDeployer(
multiProvider,
signer,
local,
remotes as unknown as string[],
writeAgentConfig,
);
}
get chains(): ChainName[] {
return this.remotes.concat([this.local]);
}
async deploy(): Promise<void> {
let contracts: HyperlaneContractsMap<CoreFactories> = {};
const owner = await this.signer.getAddress();
// First, deploy core contracts to the local chain
// NB: We create core configs for *all* chains because
// we also use coreDeployer to deploy MultisigIsms.
// Once we move that out to a HyperlaneIsmDeployer
// we can just do:
// const coreContracts = await coreDeployer.deploy();
const coreConfig = buildCoreConfig(owner, this.chains);
const coreDeployer = new HyperlaneCoreDeployer(
this.multiProvider,
coreConfig,
);
const coreContracts: HyperlaneContractsMap<CoreFactories> = {};
coreContracts[this.local] = await coreDeployer.deployContracts(
this.local,
coreConfig[this.local],
);
contracts = objMerge(contracts, coreContracts);
// Next, deploy MultisigIsms to the remote chains
// TODO: Would be cleaner if using HyperlaneIsmDeployer
const isms: ChainMap<MultisigIsmContracts> = {};
isms[this.local] = {
multisigIsm: coreContracts[this.local].multisigIsm,
};
for (const remote of this.remotes) {
isms[remote] = {
multisigIsm: await coreDeployer.deployLegacyMultisigIsm(remote),
};
}
contracts = objMerge(contracts, isms);
// Next, deploy TestRecipients to all chains
const testRecipientConfig: ChainMap<TestRecipientConfig> = objMap(
isms,
(chain, ism) => {
return { ism: ism.multisigIsm.address };
},
);
const testRecipientDeployer = new HyperlaneTestRecipientDeployer(
this.multiProvider,
testRecipientConfig,
);
const testRecipients = await testRecipientDeployer.deploy();
contracts = objMerge(contracts, testRecipients);
// Finally, deploy IGPs to all chains
// TODO: Reuse ProxyAdmin on local chain... right now *two* ProxyAdmins are deployed
const igpConfig = buildIgpConfig(owner, this.chains);
const igpDeployer = new HyperlaneIgpDeployer(this.multiProvider, igpConfig);
const igps = await igpDeployer.deploy();
contracts = objMerge(contracts, igps);
const addresses = serializeContractsMap(contracts);
// Write contract address artifacts
mergeJSON('./artifacts/', 'addresses.json', addresses);
startBlocks[this.local] = await this.multiProvider
.getProvider(this.local)
.getBlockNumber();
if (this.writeAgentConfig) {
const agentConfig = buildOverriddenAgentConfig(
this.chains,
this.multiProvider,
startBlocks,
);
// Write AgentConfig artifacts
writeJSON('./artifacts/', 'agent_config.json', agentConfig);
}
}
}

@ -0,0 +1,37 @@
import { objMerge } from '@hyperlane-xyz/sdk';
import fs from 'fs';
import path from 'path';
export function writeJSON(directory: string, filename: string, obj: any) {
if (!fs.existsSync(directory)) {
fs.mkdirSync(directory, { recursive: true });
}
fs.writeFileSync(
path.join(directory, filename),
JSON.stringify(obj, null, 2) + '\n',
);
}
export function mergeJSON(directory: string, filename: string, obj: any) {
if (fs.existsSync(path.join(directory, filename))) {
const previous = readJSON(directory, filename);
writeJSON(directory, filename, objMerge(previous, obj));
} else {
writeJSON(directory, filename, obj);
}
}
export function readFileAtPath(filepath: string) {
if (!fs.existsSync(filepath)) {
throw Error(`file doesn't exist at ${filepath}`);
}
return fs.readFileSync(filepath, 'utf8');
}
export function readJSONAtPath(filepath: string) {
return JSON.parse(readFileAtPath(filepath));
}
export function readJSON(directory: string, filename: string) {
return readJSONAtPath(path.join(directory, filename));
}

@ -0,0 +1,28 @@
{
"compilerOptions": {
"outDir": "./dist/",
"rootDir": "./",
"declaration": true,
"declarationMap": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"incremental": false,
"lib": ["es2015", "es5", "dom", "es2021"],
"module": "commonjs",
"moduleResolution": "node",
"noEmitOnError": true,
"noFallthroughCasesInSwitch": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"noUnusedLocals": true,
"preserveSymlinks": true,
"preserveWatchOutput": true,
"pretty": false,
"resolveJsonModule": true,
"sourceMap": true,
"target": "es6",
"strict": true
},
"exclude": ["./node_modules/", "./dist/"],
"include": ["./src/**/*.ts", "./config/**/*.ts", "./scripts/*.ts"]
}

@ -2,6 +2,13 @@
# yarn lockfile v1
"@cspotcode/source-map-support@^0.8.0":
version "0.8.1"
resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1"
integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==
dependencies:
"@jridgewell/trace-mapping" "0.3.9"
"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.7.0":
version "5.7.0"
resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449"
@ -344,22 +351,54 @@
"@ethersproject/properties" "^5.7.0"
"@ethersproject/strings" "^5.7.0"
"@hyperlane-xyz/core@1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@hyperlane-xyz/core/-/core-1.1.2.tgz#d084a8420136dffa63abb813ffae60f2feb10ce5"
integrity sha512-x7yUJ9NxmygQ6b5Y7Y/d9NB23bzA/8lUfbB1cmKx2j2eomST9Gwko9TI/v8KqfPDtB83bW0EFW0G31BgQnXNGg==
"@hyperlane-xyz/core@1.3.0":
version "1.3.0"
resolved "https://registry.yarnpkg.com/@hyperlane-xyz/core/-/core-1.3.0.tgz#8603ad919926e25e62e53f310d82bd010dd148c9"
integrity sha512-1YaTbucXshoijwODk+Iq6cC79iDfexsWd9/PqJZG2ogFfqoU5rO0+atK+40y5OEhLrTwCqUfRAV8K/Q+c3bYbQ==
dependencies:
"@hyperlane-xyz/utils" "1.1.2"
"@hyperlane-xyz/utils" "1.3.0"
"@openzeppelin/contracts" "^4.8.0"
"@openzeppelin/contracts-upgradeable" "^4.8.0"
"@hyperlane-xyz/utils@1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@hyperlane-xyz/utils/-/utils-1.1.2.tgz#c6f10c79bbac0a5c221991a86f79bf33574a7e91"
integrity sha512-5ox1L3uJBQJ8Gvy4HFjGTLAnr4WppXmNF9OsIJbD/qZYYr4Nk8s9Q6mj/25xej3Y7jxYH6bnJ3opUHLyG9dh/g==
"@hyperlane-xyz/sdk@^1.3.0":
version "1.3.0"
resolved "https://registry.yarnpkg.com/@hyperlane-xyz/sdk/-/sdk-1.3.0.tgz#3b8fd260ebb6954cb51576b840d837157576ac6b"
integrity sha512-pe/is3KcND01NwvDafS5AsraJGV7cK35agwbZbAXBDWf6ANU8sRXVlvQkGnOQM+lU8kyEGXCSr1TXl8YF7SG/A==
dependencies:
"@hyperlane-xyz/core" "1.3.0"
"@hyperlane-xyz/utils" "1.3.0"
"@wagmi/chains" "^0.2.6"
coingecko-api "^1.0.10"
cross-fetch "^3.1.5"
debug "^4.3.4"
ethers "^5.7.2"
zod "^3.21.2"
"@hyperlane-xyz/utils@1.3.0", "@hyperlane-xyz/utils@^1.3.0":
version "1.3.0"
resolved "https://registry.yarnpkg.com/@hyperlane-xyz/utils/-/utils-1.3.0.tgz#e7ba10b4295d10bc57feda39bb74ca879f2af6f7"
integrity sha512-jwEoJIiAZ3ZG5wlgKsiujjp+0RbvSy524iaZePjF/mqYjTTv/bl8uC5T1MW+5iHz+mgh3gXtRX2PT8yoyhuymQ==
dependencies:
ethers "^5.7.2"
"@jridgewell/resolve-uri@^3.0.3":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78"
integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==
"@jridgewell/sourcemap-codec@^1.4.10":
version "1.4.14"
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24"
integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==
"@jridgewell/trace-mapping@0.3.9":
version "0.3.9"
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9"
integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==
dependencies:
"@jridgewell/resolve-uri" "^3.0.3"
"@jridgewell/sourcemap-codec" "^1.4.10"
"@openzeppelin/contracts-upgradeable@^4.8.0":
version "4.8.0"
resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.8.0.tgz#26688982f46969018e3ed3199e72a07c8d114275"
@ -377,16 +416,102 @@
dependencies:
antlr4ts "^0.5.0-alpha.4"
"@tsconfig/node10@^1.0.7":
version "1.0.9"
resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2"
integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==
"@tsconfig/node12@^1.0.7":
version "1.0.11"
resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d"
integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==
"@tsconfig/node14@^1.0.0":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1"
integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==
"@tsconfig/node16@^1.0.2":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e"
integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==
"@types/coingecko-api@^1.0.10":
version "1.0.10"
resolved "https://registry.yarnpkg.com/@types/coingecko-api/-/coingecko-api-1.0.10.tgz#e841f75c1dc5c6ab8f251011b28a9aec0576ec19"
integrity sha512-ENJO5JzV7qTj8GfrRWAy8lom4RPQv03stvw2z9riz0z7WOXcaorc8OPov8JEekoGQ397O1BbvgPjZj7bWgqdgg==
"@types/debug@^4.1.7":
version "4.1.7"
resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.7.tgz#7cc0ea761509124709b8b2d1090d8f6c17aadb82"
integrity sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==
dependencies:
"@types/ms" "*"
"@types/ms@*":
version "0.7.31"
resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197"
integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==
"@types/node@^18.14.5":
version "18.15.11"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.11.tgz#b3b790f09cb1696cffcec605de025b088fa4225f"
integrity sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==
"@types/yargs-parser@*":
version "21.0.0"
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b"
integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==
"@types/yargs@^17.0.22":
version "17.0.24"
resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.24.tgz#b3ef8d50ad4aa6aecf6ddc97c580a00f5aa11902"
integrity sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==
dependencies:
"@types/yargs-parser" "*"
"@wagmi/chains@^0.2.6":
version "0.2.15"
resolved "https://registry.yarnpkg.com/@wagmi/chains/-/chains-0.2.15.tgz#77bd1cece0c32a795df2122cbc0564c82b63f855"
integrity sha512-yeNamxRmqq1/PirJqCpKHSJcetZ9ivZdJnCIvNvJifpCz1A2dLlD1+NON11saiyShH7tshS5Eaf0pm9Luna8JQ==
acorn-walk@^8.1.1:
version "8.2.0"
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1"
integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==
acorn@^8.4.1:
version "8.8.2"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a"
integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==
aes-js@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d"
integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==
ansi-regex@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
ansi-styles@^4.0.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
dependencies:
color-convert "^2.0.1"
antlr4ts@^0.5.0-alpha.4:
version "0.5.0-alpha.4"
resolved "https://registry.yarnpkg.com/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz#71702865a87478ed0b40c0709f422cf14d51652a"
integrity sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==
arg@^4.1.0:
version "4.1.3"
resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089"
integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==
bech32@1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9"
@ -407,6 +532,56 @@ brorand@^1.1.0:
resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==
cliui@^8.0.1:
version "8.0.1"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa"
integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==
dependencies:
string-width "^4.2.0"
strip-ansi "^6.0.1"
wrap-ansi "^7.0.0"
coingecko-api@^1.0.10:
version "1.0.10"
resolved "https://registry.yarnpkg.com/coingecko-api/-/coingecko-api-1.0.10.tgz#ac8694d5999f00727fe55f0078ce2917603076b2"
integrity sha512-7YLLC85+daxAw5QlBWoHVBVpJRwoPr4HtwanCr8V/WRjoyHTa1Lb9DQAvv4MDJZHiz4no6HGnDQnddtjV35oRA==
color-convert@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
dependencies:
color-name "~1.1.4"
color-name@~1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
create-require@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
cross-fetch@^3.1.5:
version "3.1.5"
resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f"
integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==
dependencies:
node-fetch "2.6.7"
debug@^4.3.4:
version "4.3.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
dependencies:
ms "2.1.2"
diff@^4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
elliptic@6.5.4:
version "6.5.4"
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb"
@ -420,6 +595,16 @@ elliptic@6.5.4:
minimalistic-assert "^1.0.1"
minimalistic-crypto-utils "^1.0.1"
emoji-regex@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
escalade@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
ethers@^5.7.2:
version "5.7.2"
resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e"
@ -456,6 +641,11 @@ ethers@^5.7.2:
"@ethersproject/web" "5.7.1"
"@ethersproject/wordlists" "5.7.0"
get-caller-file@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3:
version "1.1.7"
resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42"
@ -478,6 +668,11 @@ inherits@^2.0.3, inherits@^2.0.4:
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
is-fullwidth-code-point@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
js-sha3@0.8.0:
version "0.8.0"
resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840"
@ -490,6 +685,11 @@ lru-cache@^6.0.0:
dependencies:
yallist "^4.0.0"
make-error@^1.1.1:
version "1.3.6"
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
@ -500,6 +700,18 @@ minimalistic-crypto-utils@^1.0.1:
resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==
ms@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
node-fetch@2.6.7:
version "2.6.7"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==
dependencies:
whatwg-url "^5.0.0"
prettier-plugin-solidity@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/prettier-plugin-solidity/-/prettier-plugin-solidity-1.1.1.tgz#4d3375b85f97812ffcbe48d5a8b3fe914d69c91f"
@ -514,6 +726,11 @@ prettier@^2.8.2:
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.2.tgz#c4ea1b5b454d7c4b59966db2e06ed7eec5dfd160"
integrity sha512-BtRV9BcncDyI2tsuS19zzhzoxD8Dh8LiCx7j7tHzrkz8GFXAexeWFdi22mjE1d16dftH2qNaytVxqiRTGlMfpw==
require-directory@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==
scrypt-js@3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312"
@ -531,12 +748,117 @@ solidity-comments-extractor@^0.0.7:
resolved "https://registry.yarnpkg.com/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz#99d8f1361438f84019795d928b931f4e5c39ca19"
integrity sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw==
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"
tr46@~0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
ts-node@^10.9.1:
version "10.9.1"
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b"
integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==
dependencies:
"@cspotcode/source-map-support" "^0.8.0"
"@tsconfig/node10" "^1.0.7"
"@tsconfig/node12" "^1.0.7"
"@tsconfig/node14" "^1.0.0"
"@tsconfig/node16" "^1.0.2"
acorn "^8.4.1"
acorn-walk "^8.1.1"
arg "^4.1.0"
create-require "^1.1.0"
diff "^4.0.1"
make-error "^1.1.1"
v8-compile-cache-lib "^3.0.1"
yn "3.1.1"
typescript@^4.9.5:
version "4.9.5"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a"
integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==
v8-compile-cache-lib@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf"
integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==
webidl-conversions@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
whatwg-url@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==
dependencies:
tr46 "~0.0.3"
webidl-conversions "^3.0.0"
wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"
ws@7.4.6:
version "7.4.6"
resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c"
integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==
y18n@^5.0.5:
version "5.0.8"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
yallist@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
yargs-parser@^21.1.1:
version "21.1.1"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35"
integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==
yargs@^17.7.1:
version "17.7.1"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.1.tgz#34a77645201d1a8fc5213ace787c220eabbd0967"
integrity sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==
dependencies:
cliui "^8.0.1"
escalade "^3.1.1"
get-caller-file "^2.0.5"
require-directory "^2.1.1"
string-width "^4.2.3"
y18n "^5.0.5"
yargs-parser "^21.1.1"
yn@3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==
zod@^3.21.2:
version "3.21.4"
resolved "https://registry.yarnpkg.com/zod/-/zod-3.21.4.tgz#10882231d992519f0a10b5dd58a38c9dabbb64db"
integrity sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==

Loading…
Cancel
Save