diff --git a/.dockerignore b/.dockerignore index 37dd96d2..edadf75c 100644 --- a/.dockerignore +++ b/.dockerignore @@ -11,5 +11,10 @@ docs/ networks/ scratch/ +# Ignore build cache directories to avoid +# errors when addings these to docker images +build/.cache +build/.golangci-lint + go.work go.work.sum diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..a5fcd280 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,3 @@ +# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners +# Global rule: +* @rhuairahrighairidh @karzak @pirtleshell @drklee3 @nddeluca @DracoLi @evgeniy-scherbina @sesheffield @boodyvo @lbayas \ No newline at end of file diff --git a/.github/scripts/seed-internal-testnet.sh b/.github/scripts/seed-internal-testnet.sh index 19402ad4..d94a62b0 100755 --- a/.github/scripts/seed-internal-testnet.sh +++ b/.github/scripts/seed-internal-testnet.sh @@ -83,6 +83,31 @@ TETHER_USDT_CONTRACT_DEPLOY=$(npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NA TETHER_USDT_CONTRACT_ADDRESS=${TETHER_USDT_CONTRACT_DEPLOY: -42} npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$TETHER_USDT_CONTRACT_ADDRESS" 0x6767114FFAA17C6439D7AEA480738B982CE63A02 1000000000000 +# deploy and fund axlBNB ERC20 contract +AXL_BNB_CONTRACT_DEPLOY=$(npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" deploy-erc20 "axlBNB" axlBNB 18) +AXL_BNB_CONTRACT_ADDRESS=${AXL_BNB_CONTRACT_DEPLOY: -42} +npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_BNB_CONTRACT_ADDRESS" 0x6767114FFAA17C6439D7AEA480738B982CE63A02 1000000000000000000000 + +# deploy and fund axlBUSD ERC20 contract +AXL_BUSD_CONTRACT_DEPLOY=$(npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" deploy-erc20 "axlBUSD" axlBUSD 18) +AXL_BUSD_CONTRACT_ADDRESS=${AXL_BUSD_CONTRACT_DEPLOY: -42} +npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_BUSD_CONTRACT_ADDRESS" 0x6767114FFAA17C6439D7AEA480738B982CE63A02 1000000000000000000000 + +# deploy and fund axlXRPB ERC20 contract +AXL_XRPB_CONTRACT_DEPLOY=$(npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" deploy-erc20 "axlXRPB" axlXRPB 18) +AXL_XRPB_CONTRACT_ADDRESS=${AXL_XRPB_CONTRACT_DEPLOY: -42} +npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_XRPB_CONTRACT_ADDRESS" 0x6767114FFAA17C6439D7AEA480738B982CE63A02 1000000000000000000000 + +# deploy and fund axlBTC ERC20 contract +AXL_BTCB_CONTRACT_DEPLOY=$(npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" deploy-erc20 "axlBTCB" axlBTCB 18) +AXL_BTCB_CONTRACT_ADDRESS=${AXL_BTCB_CONTRACT_DEPLOY: -42} +npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_BTCB_CONTRACT_ADDRESS" 0x6767114FFAA17C6439D7AEA480738B982CE63A02 1000000000000000000000 + +# deploy and fund native wBTC ERC20 contract +WBTC_CONTRACT_DEPLOY=$(npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" deploy-erc20 "wBTC" wBTC 8) +WBTC_CONTRACT_ADDRESS=${WBTC_CONTRACT_DEPLOY: -42} +npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$WBTC_CONTRACT_ADDRESS" 0x6767114FFAA17C6439D7AEA480738B982CE63A02 100000000000000000 + # seed some evm wallets npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_WBTC_CONTRACT_ADDRESS" "$DEV_TEST_WALLET_ADDRESS" 10000000000000 npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$MULTICHAIN_wBTC_CONTRACT_ADDRESS" "$DEV_TEST_WALLET_ADDRESS" 10000000000000 @@ -91,6 +116,11 @@ npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$wETH_CONTRAC npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_USDC_CONTRACT_ADDRESS" "$DEV_TEST_WALLET_ADDRESS" 100000000000 npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$MULTICHAIN_USDT_CONTRACT_ADDRESS" "$DEV_TEST_WALLET_ADDRESS" 100000000000 npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$TETHER_USDT_CONTRACT_ADDRESS" "$DEV_TEST_WALLET_ADDRESS" 1000000000000 +npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_BNB_CONTRACT_ADDRESS" "$DEV_TEST_WALLET_ADDRESS" 1000000000000000000000 +npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_BUSD_CONTRACT_ADDRESS" "$DEV_TEST_WALLET_ADDRESS" 1000000000000000000000 +npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_XRPB_CONTRACT_ADDRESS" "$DEV_TEST_WALLET_ADDRESS" 1000000000000000000000 +npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_BTCB_CONTRACT_ADDRESS" "$DEV_TEST_WALLET_ADDRESS" 1000000000000000000000 +npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$WBTC_CONTRACT_ADDRESS" "$DEV_TEST_WALLET_ADDRESS" 10000000000000 # seed webapp E2E whale account npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_WBTC_CONTRACT_ADDRESS" "$WEBAPP_E2E_WHALE_ADDRESS" 100000000000000 npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$MULTICHAIN_wBTC_CONTRACT_ADDRESS" "$WEBAPP_E2E_WHALE_ADDRESS" 10000000000000 @@ -99,6 +129,11 @@ npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$wETH_CONTRAC npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_USDC_CONTRACT_ADDRESS" "$WEBAPP_E2E_WHALE_ADDRESS" 10000000000000 npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$MULTICHAIN_USDT_CONTRACT_ADDRESS" "$WEBAPP_E2E_WHALE_ADDRESS" 1000000000000 npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$TETHER_USDT_CONTRACT_ADDRESS" "$WEBAPP_E2E_WHALE_ADDRESS" 1000000000000 +npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_BNB_CONTRACT_ADDRESS" "$WEBAPP_E2E_WHALE_ADDRESS" 10000000000000000000000 +npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_BUSD_CONTRACT_ADDRESS" "$WEBAPP_E2E_WHALE_ADDRESS" 10000000000000000000000 +npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_BTCB_CONTRACT_ADDRESS" "$WEBAPP_E2E_WHALE_ADDRESS" 10000000000000000000000 +npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$AXL_XRPB_CONTRACT_ADDRESS" "$WEBAPP_E2E_WHALE_ADDRESS" 10000000000000000000000 +npx hardhat --network "${ERC20_DEPLOYER_NETWORK_NAME}" mint-erc20 "$WBTC_CONTRACT_ADDRESS" "$WBTC_CONTRACT_ADDRESS" 10000000000000 # give dev-wallet enough delegation power to pass proposals by itself @@ -138,7 +173,7 @@ PARAM_CHANGE_PROP_TEMPLATE=$( { "subspace": "evmutil", "key": "EnabledConversionPairs", - "value": "[{\"kava_erc20_address\":\"MULTICHAIN_USDC_CONTRACT_ADDRESS\",\"denom\":\"erc20/multichain/usdc\"},{\"kava_erc20_address\":\"MULTICHAIN_USDT_CONTRACT_ADDRESS\",\"denom\":\"erc20/multichain/usdt\"},{\"kava_erc20_address\":\"MULTICHAIN_wBTC_CONTRACT_ADDRESS\",\"denom\":\"erc20/multichain/wbtc\"},{\"kava_erc20_address\":\"AXL_USDC_CONTRACT_ADDRESS\",\"denom\":\"erc20/axelar/usdc\"},{\"kava_erc20_address\":\"AXL_WBTC_CONTRACT_ADDRESS\",\"denom\":\"erc20/axelar/wbtc\"},{\"kava_erc20_address\":\"wETH_CONTRACT_ADDRESS\",\"denom\":\"erc20/axelar/eth\"},{\"kava_erc20_address\":\"TETHER_USDT_CONTRACT_ADDRESS\",\"denom\":\"erc20/tether/usdt\"}]" + "value": "[{\"kava_erc20_address\":\"MULTICHAIN_USDC_CONTRACT_ADDRESS\",\"denom\":\"erc20/multichain/usdc\"},{\"kava_erc20_address\":\"MULTICHAIN_USDT_CONTRACT_ADDRESS\",\"denom\":\"erc20/multichain/usdt\"},{\"kava_erc20_address\":\"MULTICHAIN_wBTC_CONTRACT_ADDRESS\",\"denom\":\"erc20/multichain/wbtc\"},{\"kava_erc20_address\":\"AXL_USDC_CONTRACT_ADDRESS\",\"denom\":\"erc20/axelar/usdc\"},{\"kava_erc20_address\":\"AXL_WBTC_CONTRACT_ADDRESS\",\"denom\":\"erc20/axelar/wbtc\"},{\"kava_erc20_address\":\"wETH_CONTRACT_ADDRESS\",\"denom\":\"erc20/axelar/eth\"},{\"kava_erc20_address\":\"TETHER_USDT_CONTRACT_ADDRESS\",\"denom\":\"erc20/tether/usdt\"},{\"kava_erc20_address\":\"AXL_BNB_CONTRACT_ADDRESS\",\"denom\":\"bnb\"},{\"kava_erc20_address\":\"AXL_BUSD_CONTRACT_ADDRESS\",\"denom\":\"busd\"},{\"kava_erc20_address\":\"AXL_BTCB_CONTRACT_ADDRESS\",\"denom\":\"btcb\"},{\"kava_erc20_address\":\"AXL_XRPB_CONTRACT_ADDRESS\",\"denom\":\"xrpb\"},{\"kava_erc20_address\":\"WBTC_CONTRACT_ADDRESS\",\"denom\":\"erc20/bitgo/wbtc\"}]" } ] } @@ -155,6 +190,11 @@ finalProposal="${finalProposal/AXL_USDC_CONTRACT_ADDRESS/$AXL_USDC_CONTRACT_ADDR finalProposal="${finalProposal/AXL_WBTC_CONTRACT_ADDRESS/$AXL_WBTC_CONTRACT_ADDRESS}" finalProposal="${finalProposal/wETH_CONTRACT_ADDRESS/$wETH_CONTRACT_ADDRESS}" finalProposal="${finalProposal/TETHER_USDT_CONTRACT_ADDRESS/$TETHER_USDT_CONTRACT_ADDRESS}" +finalProposal="${finalProposal/AXL_BNB_CONTRACT_ADDRESS/$AXL_BNB_CONTRACT_ADDRESS}" +finalProposal="${finalProposal/AXL_BUSD_CONTRACT_ADDRESS/$AXL_BUSD_CONTRACT_ADDRESS}" +finalProposal="${finalProposal/AXL_BTCB_CONTRACT_ADDRESS/$AXL_BTCB_CONTRACT_ADDRESS}" +finalProposal="${finalProposal/AXL_XRPB_CONTRACT_ADDRESS/$AXL_XRPB_CONTRACT_ADDRESS}" +finalProposal="${finalProposal/WBTC_CONTRACT_ADDRESS/$WBTC_CONTRACT_ADDRESS}" # create unique proposal filename proposalFileName="$(date +%s)-proposal.json" @@ -185,6 +225,21 @@ sleep $AVG_SECONDS_BETWEEN_BLOCKS updatedEvmUtilParams=$(curl https://api.app.internal.testnet.us-east.production.kava.io/kava/evmutil/v1beta1/params) printf "updated evm util module params\n %s" , "$updatedEvmUtilParams" +# submit a kava token committee proposal +COMMITTEE_PROP_TEMPLATE=$( + cat <<'END_HEREDOC' +{ + "@type": "/cosmos.gov.v1beta1.TextProposal", + "title": "The next big thing signaling proposal.", + "description": "The purpose of this proposal is to signal support/opposition to the next big thing" +} +END_HEREDOC +) +committeeProposalFileName="$(date +%s)-committee-proposal.json" +echo "$COMMITTEE_PROP_TEMPLATE" >$committeeProposalFileName +tokenCommitteeId=4 +kava tx committee submit-proposal "$tokenCommitteeId" "$committeeProposalFileName" --gas auto --gas-adjustment 1.5 --gas-prices 0.01ukava --from god -y + # if adding more cosmos coins -> er20s, ensure that the deployment order below remains the same. # convert 1 HARD to an erc20. doing this ensures the contract is deployed. kava tx evmutil convert-cosmos-coin-to-erc20 \ diff --git a/.github/workflows/cd-internal-testnet-manual.yml b/.github/workflows/cd-internal-testnet-manual.yml deleted file mode 100644 index bcb84cf9..00000000 --- a/.github/workflows/cd-internal-testnet-manual.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: Manual Deployment (Internal Testnet) -# allow to be triggered manually -on: workflow_dispatch - -jobs: - # in order: - # enter standby (prevents autoscaling group from killing node during deploy) - # stop kava - # take ebs + zfs snapshots - # download updated binary and genesis - # reset application database state (only done on internal testnet) - reset-chain-to-zero-state: - uses: ./.github/workflows/cd-reset-internal-testnet.yml - with: - aws-region: us-east-1 - chain-id: kava_2221-17000 - ssm-document-name: kava-testnet-internal-node-update - playbook-name: reset-internal-testnet-playbook.yml - playbook-infrastructure-branch: master - secrets: inherit - - # start kava with new binary and genesis state on api, peer and seed nodes, place nodes in service once they start and are synched to live - start-chain-api: - uses: ./.github/workflows/cd-start-chain.yml - with: - aws-region: us-east-1 - chain-id: kava_2221-17000 - ssm-document-name: kava-testnet-internal-node-update - playbook-name: start-chain-api-playbook.yml - playbook-infrastructure-branch: master - secrets: inherit - needs: [reset-chain-to-zero-state] - - # setup test and development accounts and balances, deploy contracts by calling the chain's api - seed-chain-state: - uses: ./.github/workflows/cd-seed-chain.yml - with: - chain-api-url: https://rpc.app.internal.testnet.us-east.production.kava.io:443 - chain-id: kava_2221-17000 - seed-script-filename: seed-internal-testnet.sh - erc20-deployer-network-name: internal_testnet - genesis_validator_addresses: "kavavaloper1xcgtffvv2yeqmgs3yz4gv29kgjrj8usxrnrlwp kavavaloper1w66m9hdzwgd6uc8g93zqkcumgwzrpcw958sh3s" - kava_version_filepath: ./ci/env/kava-internal-testnet/KAVA.VERSION - secrets: inherit - needs: [start-chain-api] - post-pipeline-metrics: - uses: ./.github/workflows/metric-pipeline.yml - if: always() # always run so we metric failures and successes - with: - aws-region: us-east-1 - metric-name: kava.deploys.testnet.internal - namespace: Kava/ContinuousDeployment - secrets: inherit - needs: [seed-chain-state] diff --git a/.github/workflows/cd-internal-testnet.yml b/.github/workflows/cd-internal-testnet.yml deleted file mode 100644 index ed06faf4..00000000 --- a/.github/workflows/cd-internal-testnet.yml +++ /dev/null @@ -1,79 +0,0 @@ -name: Continuous Deployment (Internal Testnet) -# run after every successful CI job of new commits to the master branch -# if deploy version or config has changed -on: - workflow_run: - workflows: [Continuous Integration (Kava Master)] - types: - - completed - -jobs: - changed_files: - runs-on: ubuntu-latest - # define output for first job forwarding output of changedInternalTestnetConfig job - outputs: - changedInternalTestnetConfig: ${{ steps.changed-internal-testnet-config.outputs.any_changed }} - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 # OR "2" -> To retrieve the preceding commit. - - name: Get all changed internal testnet files - id: changed-internal-testnet-config - uses: tj-actions/changed-files@v42 - with: - # Avoid using single or double quotes for multiline patterns - files: | - ci/env/kava-internal-testnet/** - - # in order: - # enter standby (prevents autoscaling group from killing node during deploy) - # stop kava - # take ebs + zfs snapshots - # download updated binary and genesis - # reset application database state (only done on internal testnet) - reset-chain-to-zero-state: - needs: [changed_files] - # only start cd pipeline if last ci run was successful - if: ${{ github.event.workflow_run.conclusion == 'success' && needs.changed_files.outputs.changedInternalTestnetConfig == 'true' }} - uses: ./.github/workflows/cd-reset-internal-testnet.yml - with: - aws-region: us-east-1 - chain-id: kava_2221-17000 - ssm-document-name: kava-testnet-internal-node-update - playbook-name: reset-internal-testnet-playbook.yml - playbook-infrastructure-branch: master - secrets: inherit - - # start kava with new binary and genesis state on api, peer and seed nodes, place nodes in service once they start and are synched to live - start-chain-api: - uses: ./.github/workflows/cd-start-chain.yml - with: - aws-region: us-east-1 - chain-id: kava_2221-17000 - ssm-document-name: kava-testnet-internal-node-update - playbook-name: start-chain-api-playbook.yml - playbook-infrastructure-branch: master - secrets: inherit - needs: [reset-chain-to-zero-state] - - # setup test and development accounts and balances, deploy contracts by calling the chain's api - seed-chain-state: - uses: ./.github/workflows/cd-seed-chain.yml - with: - chain-api-url: https://rpc.app.internal.testnet.us-east.production.kava.io:443 - chain-id: kava_2221-17000 - seed-script-filename: seed-internal-testnet.sh - erc20-deployer-network-name: internal_testnet - genesis_validator_addresses: "kavavaloper1xcgtffvv2yeqmgs3yz4gv29kgjrj8usxrnrlwp kavavaloper1w66m9hdzwgd6uc8g93zqkcumgwzrpcw958sh3s" - kava_version_filepath: ./ci/env/kava-internal-testnet/KAVA.VERSION - secrets: inherit - needs: [start-chain-api] - post-pipeline-metrics: - uses: ./.github/workflows/metric-pipeline.yml - if: always() # always run so we metric failures and successes - with: - aws-region: us-east-1 - metric-name: kava.deploys.testnet.internal - namespace: Kava/ContinuousDeployment - secrets: inherit - needs: [seed-chain-state] diff --git a/.github/workflows/cd-protonet-manual.yml b/.github/workflows/cd-protonet-manual.yml deleted file mode 100644 index b723799d..00000000 --- a/.github/workflows/cd-protonet-manual.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: Manual Deployment (Protonet) -# allow to be triggered manually -on: workflow_dispatch - -jobs: -# in order: - # enter standby (prevents autoscaling group from killing node during deploy) - # stop kava - # take ebs + zfs snapshots - # download updated binary and genesis - # reset application database state (only done on internal testnet) - reset-chain-to-zero-state: - uses: ./.github/workflows/cd-reset-internal-testnet.yml - with: - aws-region: us-east-1 - chain-id: proto_2221-17000 - ssm-document-name: kava-testnet-internal-node-update - playbook-name: reset-protonet-playbook.yml - playbook-infrastructure-branch: master - secrets: inherit - - # start kava with new binary and genesis state on api, peer and seed nodes, place nodes in service once they start and are synched to live - start-chain-api: - uses: ./.github/workflows/cd-start-chain.yml - with: - aws-region: us-east-1 - chain-id: proto_2221-17000 - ssm-document-name: kava-testnet-internal-node-update - playbook-name: start-chain-api-playbook.yml - playbook-infrastructure-branch: master - secrets: inherit - needs: [reset-chain-to-zero-state] - - # setup test and development accounts and balances, deploy contracts by calling the chain's api - seed-chain-state: - uses: ./.github/workflows/cd-seed-chain.yml - with: - chain-api-url: https://rpc.app.protonet.us-east.production.kava.io:443 - chain-id: proto_2221-17000 - seed-script-filename: seed-protonet.sh - erc20-deployer-network-name: protonet - genesis_validator_addresses: "kavavaloper14w4avgdvqrlpww6l5dhgj4egfn6ln7gmtp7r2m" - kava_version_filepath: ./ci/env/kava-protonet/KAVA.VERSION - secrets: inherit - needs: [start-chain-api] - post-pipeline-metrics: - uses: ./.github/workflows/metric-pipeline.yml - if: always() # always run so we metric failures and successes - with: - aws-region: us-east-1 - metric-name: kava.deploys.testnet.proto - namespace: Kava/ContinuousDeployment - secrets: inherit - needs: [seed-chain-state] diff --git a/.github/workflows/cd-protonet.yml b/.github/workflows/cd-protonet.yml deleted file mode 100644 index 5da8d9a2..00000000 --- a/.github/workflows/cd-protonet.yml +++ /dev/null @@ -1,60 +0,0 @@ -name: Continuous Deployment (Protonet) -# run after every successful CI job of new commits to the master branch -on: - workflow_run: - workflows: [Continuous Integration (Kava Master)] - types: - - completed - -jobs: - # in order: - # enter standby (prevents autoscaling group from killing node during deploy) - # stop kava - # take ebs + zfs snapshots - # download updated binary and genesis - # reset application database state (only done on internal testnet) - reset-chain-to-zero-state: - # only start cd pipeline if last ci run was successful - if: ${{ github.event.workflow_run.conclusion == 'success' }} - uses: ./.github/workflows/cd-reset-internal-testnet.yml - with: - aws-region: us-east-1 - chain-id: proto_2221-17000 - ssm-document-name: kava-testnet-internal-node-update - playbook-name: reset-protonet-playbook.yml - playbook-infrastructure-branch: master - secrets: inherit - - # start kava with new binary and genesis state on api, peer and seed nodes, place nodes in service once they start and are synched to live - start-chain-api: - uses: ./.github/workflows/cd-start-chain.yml - with: - aws-region: us-east-1 - chain-id: proto_2221-17000 - ssm-document-name: kava-testnet-internal-node-update - playbook-name: start-chain-api-playbook.yml - playbook-infrastructure-branch: master - secrets: inherit - needs: [reset-chain-to-zero-state] - - # setup test and development accounts and balances, deploy contracts by calling the chain's api - seed-chain-state: - uses: ./.github/workflows/cd-seed-chain.yml - with: - chain-api-url: https://rpc.app.protonet.us-east.production.kava.io:443 - chain-id: proto_2221-17000 - seed-script-filename: seed-protonet.sh - erc20-deployer-network-name: protonet - genesis_validator_addresses: "kavavaloper14w4avgdvqrlpww6l5dhgj4egfn6ln7gmtp7r2m" - kava_version_filepath: ./ci/env/kava-protonet/KAVA.VERSION - secrets: inherit - needs: [start-chain-api] - post-pipeline-metrics: - uses: ./.github/workflows/metric-pipeline.yml - if: always() # always run so we metric failures and successes - with: - aws-region: us-east-1 - metric-name: kava.deploys.testnet.proto - namespace: Kava/ContinuousDeployment - secrets: inherit - needs: [seed-chain-state] diff --git a/.github/workflows/cd-reset-internal-testnet.yml b/.github/workflows/cd-reset-internal-testnet.yml deleted file mode 100644 index 9df50d7a..00000000 --- a/.github/workflows/cd-reset-internal-testnet.yml +++ /dev/null @@ -1,80 +0,0 @@ -name: Reset Internal Testnet - -on: - workflow_call: - inputs: - chain-id: - required: true - type: string - aws-region: - required: true - type: string - ssm-document-name: - required: true - type: string - playbook-name: - required: true - type: string - playbook-infrastructure-branch: - required: true - type: string - secrets: - CI_AWS_KEY_ID: - required: true - CI_AWS_KEY_SECRET: - required: true - KAVA_PRIVATE_GITHUB_ACCESS_TOKEN: - required: true - -# in order: -# enter standby (prevents autoscaling group from killing node during deploy) -# stop kava -# download updated binary and genesis -# reset application database state (only done on internal testnet) -jobs: - place-chain-nodes-on-standby: - runs-on: ubuntu-latest - steps: - - name: checkout repo from current commit - uses: actions/checkout@v4 - - name: take the chain offline - run: bash ${GITHUB_WORKSPACE}/.github/scripts/put-all-chain-nodes-on-standby.sh - env: - CHAIN_ID: ${{ inputs.chain-id }} - AWS_REGION: ${{ inputs.aws-region }} - AWS_ACCESS_KEY_ID: ${{ secrets.CI_AWS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.CI_AWS_KEY_SECRET }} - - name: checkout infrastructure repo - uses: actions/checkout@v4 - with: - repository: Kava-Labs/infrastructure - token: ${{ secrets.KAVA_PRIVATE_GITHUB_ACCESS_TOKEN }} - path: infrastructure - ref: master - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version-file: go.mod - - name: build kava node updater - run: cd infrastructure/cli/kava-node-updater && make install && cd ../../../ - - name: run reset playbook on all chain nodes - run: | - kava-node-updater \ - --debug \ - --max-retries=2 \ - --aws-ssm-document-name=$SSM_DOCUMENT_NAME \ - --infrastructure-git-pointer=$PLAYBOOK_INFRASTRUCTURE_BRANCH \ - --update-playbook-filename=$PLAYBOOK_NAME \ - --chain-id=$CHAIN_ID \ - --max-upgrade-batch-size=0 \ - --node-states=Standby \ - --wait-for-node-sync-after-upgrade=false - env: - SSM_DOCUMENT_NAME: ${{ inputs.ssm-document-name }} - PLAYBOOK_NAME: ${{ inputs.playbook-name }} - CHAIN_ID: ${{ inputs.chain-id }} - AWS_REGION: ${{ inputs.aws-region }} - AWS_ACCESS_KEY_ID: ${{ secrets.CI_AWS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.CI_AWS_KEY_SECRET }} - AWS_SDK_LOAD_CONFIG: 1 - PLAYBOOK_INFRASTRUCTURE_BRANCH: ${{ inputs.playbook-infrastructure-branch }} diff --git a/.github/workflows/cd-seed-chain.yml b/.github/workflows/cd-seed-chain.yml deleted file mode 100644 index 43cf6e87..00000000 --- a/.github/workflows/cd-seed-chain.yml +++ /dev/null @@ -1,94 +0,0 @@ -name: Seed Chain - -on: - workflow_call: - inputs: - chain-api-url: - required: true - type: string - chain-id: - required: true - type: string - seed-script-filename: - required: true - type: string - erc20-deployer-network-name: - required: true - type: string - genesis_validator_addresses: - required: true - type: string - kava_version_filepath: - required: true - type: string - secrets: - DEV_WALLET_MNEMONIC: - required: true - KAVA_TESTNET_GOD_MNEMONIC: - required: true - -jobs: - seed-chain-state: - runs-on: ubuntu-latest - steps: - - name: checkout repo from master - uses: actions/checkout@v4 - with: - ref: master - - name: checkout version of kava used by network - run: | - git pull -p - git checkout $(cat ${KAVA_VERSION_FILEPATH}) - env: - KAVA_VERSION_FILEPATH: ${{ inputs.kava_version_filepath }} - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version-file: go.mod - - name: build kava binary - run: make install - - name: checkout go evm tools repo - uses: actions/checkout@v4 - with: - repository: ethereum/go-ethereum - path: go-ethereum - ref: v1.10.26 - - name: install go evm tools - run: | - make - make devtools - working-directory: go-ethereum - - name: checkout kava bridge repo for deploying evm contracts - uses: actions/checkout@v4 - with: - repository: Kava-Labs/kava-bridge - path: kava-bridge - ref: main - - name: install nodeJS - uses: actions/setup-node@v3 - with: - cache: npm - node-version: 18 - cache-dependency-path: kava-bridge/contract/package.json - - name: "install ERC20 contract deployment dependencies" - run: "npm install" - working-directory: kava-bridge/contract - - name: compile default erc20 contracts - run: make compile-contracts - working-directory: kava-bridge - - name: download seed script from current commit - run: wget https://raw.githubusercontent.com/Kava-Labs/kava/${GITHUB_SHA}/.github/scripts/${SEED_SCRIPT_FILENAME} && chmod +x ${SEED_SCRIPT_FILENAME} - working-directory: kava-bridge/contract - env: - SEED_SCRIPT_FILENAME: ${{ inputs.seed-script-filename }} - - name: run seed scripts - run: bash ./${SEED_SCRIPT_FILENAME} - working-directory: kava-bridge/contract - env: - CHAIN_API_URL: ${{ inputs.chain-api-url }} - CHAIN_ID: ${{ inputs.chain-id }} - DEV_WALLET_MNEMONIC: ${{ secrets.DEV_WALLET_MNEMONIC }} - KAVA_TESTNET_GOD_MNEMONIC: ${{ secrets.KAVA_TESTNET_GOD_MNEMONIC }} - SEED_SCRIPT_FILENAME: ${{ inputs.seed-script-filename }} - ERC20_DEPLOYER_NETWORK_NAME: ${{ inputs.erc20-deployer-network-name }} - GENESIS_VALIDATOR_ADDRESSES: ${{ inputs.genesis_validator_addresses }} diff --git a/.github/workflows/cd-start-chain.yml b/.github/workflows/cd-start-chain.yml deleted file mode 100644 index 02ee3065..00000000 --- a/.github/workflows/cd-start-chain.yml +++ /dev/null @@ -1,78 +0,0 @@ -name: Start Chain - -on: - workflow_call: - inputs: - chain-id: - required: true - type: string - aws-region: - required: true - type: string - ssm-document-name: - required: true - type: string - playbook-name: - required: true - type: string - playbook-infrastructure-branch: - required: true - type: string - secrets: - CI_AWS_KEY_ID: - required: true - CI_AWS_KEY_SECRET: - required: true - KAVA_PRIVATE_GITHUB_ACCESS_TOKEN: - required: true - -jobs: - # start kava, allow nodes to start processing requests from users once they are synced to live - serve-traffic: - runs-on: ubuntu-latest - steps: - - name: checkout repo from current commit - uses: actions/checkout@v4 - - name: take the chain offline - run: bash ${GITHUB_WORKSPACE}/.github/scripts/put-all-chain-nodes-on-standby.sh - env: - CHAIN_ID: ${{ inputs.chain-id }} - AWS_REGION: ${{ inputs.aws-region }} - AWS_ACCESS_KEY_ID: ${{ secrets.CI_AWS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.CI_AWS_KEY_SECRET }} - - name: checkout infrastructure repo - uses: actions/checkout@v4 - with: - repository: Kava-Labs/infrastructure - token: ${{ secrets.KAVA_PRIVATE_GITHUB_ACCESS_TOKEN }} - path: infrastructure - ref: master - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version-file: go.mod - - name: build kava node updater - run: cd infrastructure/cli/kava-node-updater && make install && cd ../../../ - - name: run start-chain playbook on all chain nodes - run: | - kava-node-updater \ - --debug \ - --max-retries=2 \ - --aws-ssm-document-name=$SSM_DOCUMENT_NAME \ - --infrastructure-git-pointer=$PLAYBOOK_INFRASTRUCTURE_BRANCH \ - --update-playbook-filename=$PLAYBOOK_NAME \ - --chain-id=$CHAIN_ID \ - --max-upgrade-batch-size=0 \ - --node-states=Standby \ - --wait-for-node-sync-after-upgrade=true - env: - SSM_DOCUMENT_NAME: ${{ inputs.ssm-document-name }} - PLAYBOOK_NAME: ${{ inputs.playbook-name }} - CHAIN_ID: ${{ inputs.chain-id }} - AWS_REGION: ${{ inputs.aws-region }} - AWS_ACCESS_KEY_ID: ${{ secrets.CI_AWS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.CI_AWS_KEY_SECRET }} - AWS_SDK_LOAD_CONFIG: 1 - PLAYBOOK_INFRASTRUCTURE_BRANCH: ${{ inputs.playbook-infrastructure-branch }} - - name: bring the chain online - run: bash ${GITHUB_WORKSPACE}/.github/scripts/exit-standby-all-chain-nodes.sh diff --git a/.github/workflows/ci-commit.yml b/.github/workflows/ci-commit.yml deleted file mode 100644 index 79b7f2bb..00000000 --- a/.github/workflows/ci-commit.yml +++ /dev/null @@ -1,7 +0,0 @@ -name: Continuous Integration (Commit) -on: - push: -# run per commit ci checks against this commit -jobs: - lint: - uses: ./.github/workflows/ci-lint.yml diff --git a/.github/workflows/ci-default.yml b/.github/workflows/ci-default.yml deleted file mode 100644 index 84806729..00000000 --- a/.github/workflows/ci-default.yml +++ /dev/null @@ -1,79 +0,0 @@ -name: Continuous Integration (Default Checks) - -on: - workflow_call: -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: checkout repo from current commit - uses: actions/checkout@v4 - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version-file: go.mod - cache-dependency-path: | - go.sum - tests/e2e/kvtool/go.sum - - name: build application - run: make build - test: - runs-on: ubuntu-latest - steps: - - name: checkout repo from current commit - uses: actions/checkout@v4 - with: - submodules: true - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version-file: go.mod - cache-dependency-path: | - go.sum - tests/e2e/kvtool/go.sum - - name: run unit tests - run: make test - - name: run e2e tests - run: make docker-build test-e2e - validate-internal-testnet-genesis: - runs-on: ubuntu-latest - steps: - - name: checkout repo from current commit - uses: actions/checkout@v4 - - name: save version of kava that will be deployed if this pr is merged - id: kava-version - run: | - echo "KAVA_VERSION=$(cat ./ci/env/kava-internal-testnet/KAVA.VERSION)" >> $GITHUB_OUTPUT - - name: checkout repo from master - uses: actions/checkout@v4 - with: - ref: master - - name: checkout version of kava that will be deployed if this pr is merged - run: | - git pull -p - git checkout $KAVA_VERSION - env: - KAVA_VERSION: ${{ steps.kava-version.outputs.KAVA_VERSION }} - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version-file: go.mod - - name: build kava cli - run: make install - - name: checkout repo from current commit to validate current branch's genesis - uses: actions/checkout@v4 - - name: validate testnet genesis - run: kava validate-genesis ci/env/kava-internal-testnet/genesis.json - validate-protonet-genesis: - runs-on: ubuntu-latest - steps: - - name: checkout repo from current commit - uses: actions/checkout@v4 - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version-file: go.mod - - name: build kava cli - run: make install - - name: validate protonet genesis - run: kava validate-genesis ci/env/kava-protonet/genesis.json diff --git a/.github/workflows/ci-docker.yml b/.github/workflows/ci-docker.yml deleted file mode 100644 index 067f6055..00000000 --- a/.github/workflows/ci-docker.yml +++ /dev/null @@ -1,102 +0,0 @@ -name: Build & Publish Docker Images - -on: - workflow_call: - inputs: - dockerhub-username: - required: true - type: string - # this workflow publishes a rocksdb & goleveldb docker images with these tags: - # - -goleveldb - # - -goleveldb - # - -rocksdb - # - -rocksdb - extra-image-tag: - required: true - type: string - secrets: - CI_DOCKERHUB_TOKEN: - required: true - -# runs in ci-master after successful checks -# you can use images built by this action in future jobs. -# https://docs.docker.com/build/ci/github-actions/examples/#share-built-image-between-jobs -jobs: - docker-goleveldb: - # https://github.com/marketplace/actions/build-and-push-docker-images - runs-on: ubuntu-latest - steps: - # ensure working with latest code - - name: Checkout - uses: actions/checkout@v4 - - # generate a git commit hash to be used as image tag - - name: Generate short hash - id: commit-hash - run: echo "short=$( git rev-parse --short $GITHUB_SHA )" >> $GITHUB_OUTPUT - - # qemu is used to emulate different platform architectures - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - # cross-platform build of the image - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - # authenticate for publish to docker hub - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ inputs.dockerhub-username }} - password: ${{ secrets.CI_DOCKERHUB_TOKEN }} - - # publish to docker hub, tag with short git hash - - name: Build and push (goleveldb) - uses: docker/build-push-action@v5 - with: - context: . - cache-from: type=gha - cache-to: type=gha,mode=max - platforms: linux/amd64,linux/arm64 - push: true - tags: kava/kava:${{ steps.commit-hash.outputs.short }}-goleveldb,kava/kava:${{ inputs.extra-image-tag }}-goleveldb - - docker-rocksdb: - # https://github.com/marketplace/actions/build-and-push-docker-images - runs-on: ubuntu-latest - steps: - # ensure working with latest code - - name: Checkout - uses: actions/checkout@v4 - - # generate a git commit hash to be used as image tag - - name: Generate short hash - id: commit-hash - run: echo "short=$( git rev-parse --short $GITHUB_SHA )" >> $GITHUB_OUTPUT - - # qemu is used to emulate different platform architectures - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - # cross-platform build of the image - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - # authenticate for publish to docker hub - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ inputs.dockerhub-username }} - password: ${{ secrets.CI_DOCKERHUB_TOKEN }} - - # publish to docker hub, tag with short git hash - - name: Build and push (rocksdb) - uses: docker/build-push-action@v5 - with: - context: . - file: Dockerfile-rocksdb - cache-from: type=gha - cache-to: type=gha,mode=max - platforms: linux/amd64,linux/arm64 - push: true - tags: kava/kava:${{ steps.commit-hash.outputs.short }}-rocksdb,kava/kava:${{ inputs.extra-image-tag }}-rocksdb diff --git a/.github/workflows/ci-lint.yml b/.github/workflows/ci-lint.yml deleted file mode 100644 index 7c36c835..00000000 --- a/.github/workflows/ci-lint.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: Lint Checks -on: - workflow_call: -# run per commit ci checks against this commit -jobs: - proto-lint: - uses: ./.github/workflows/proto.yml - golangci-lint: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: golangci-lint - uses: reviewdog/action-golangci-lint@v2 - with: - github_token: ${{ secrets.github_token }} - reporter: github-pr-review - golangci_lint_flags: --timeout 10m diff --git a/.github/workflows/ci-master.yml b/.github/workflows/ci-master.yml deleted file mode 100644 index 8a4750d1..00000000 --- a/.github/workflows/ci-master.yml +++ /dev/null @@ -1,56 +0,0 @@ -name: Continuous Integration (Kava Master) -on: - push: - # run CI on any push to the master branch - branches: - - master -jobs: - # run per commit ci checks against master branch - lint-checks: - uses: ./.github/workflows/ci-lint.yml - # run default ci checks against master branch - default-checks: - uses: ./.github/workflows/ci-default.yml - # build and upload versions of kava for use on internal infrastructure - # configurations for databases, cpu architectures and operating systems - publish-internal: - # only run if all checks pass - needs: [lint-checks, default-checks] - runs-on: ubuntu-latest - steps: - - name: checkout repo from current commit - uses: actions/checkout@v4 - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version-file: go.mod - - name: set build tag - run: echo "BUILD_TAG=$(date +%s)-$(git rev-parse HEAD | cut -c 1-8)" >> $GITHUB_ENV - - name: build rocksdb dependency - run: bash ${GITHUB_WORKSPACE}/.github/scripts/install-rocksdb.sh - env: - ROCKSDB_VERSION: v8.10.0 - - name: Build and upload release artifacts - run: bash ${GITHUB_WORKSPACE}/.github/scripts/publish-internal-release-artifacts.sh - env: - BUILD_TAG: ${{ env.BUILD_TAG }} - AWS_REGION: us-east-1 - AWS_ACCESS_KEY_ID: ${{ secrets.CI_AWS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.CI_AWS_KEY_SECRET }} - docker: - # only run if all checks pass - needs: [lint-checks, default-checks] - uses: ./.github/workflows/ci-docker.yml - with: - dockerhub-username: kavaops - extra-image-tag: master - secrets: inherit - post-pipeline-metrics: - uses: ./.github/workflows/metric-pipeline.yml - if: always() # always run so we metric failures and successes - with: - aws-region: us-east-1 - metric-name: kava.releases.merge - namespace: Kava/ContinuousIntegration - secrets: inherit - needs: [publish-internal] diff --git a/.github/workflows/ci-pr.yml b/.github/workflows/ci-pr.yml deleted file mode 100644 index 5222c788..00000000 --- a/.github/workflows/ci-pr.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Continuous Integration (PR) -on: - pull_request: - # run CI on pull requests to master or a release branch - branches: - - master - - 'release/**' - - 'releases/**' -# run default ci checks against current PR -jobs: - default: - uses: ./.github/workflows/ci-default.yml - rocksdb: - uses: ./.github/workflows/ci-rocksdb-build.yml - post-pipeline-metrics: - uses: ./.github/workflows/metric-pipeline.yml - if: always() # always run so we metric failures and successes - with: - aws-region: us-east-1 - metric-name: kava.releases.pr - namespace: Kava/ContinuousIntegration - secrets: inherit - needs: [default] diff --git a/.github/workflows/ci-release.yml b/.github/workflows/ci-release.yml deleted file mode 100644 index bc8aa955..00000000 --- a/.github/workflows/ci-release.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: Continuous Integration (Release) -on: - push: - tags: - - "v[0-9]+.[0-9]+.[0-9]+*" -jobs: - # run per commit ci checks against released version - lint-checks: - uses: ./.github/workflows/ci-lint.yml - # run default ci checks against released version - default-checks: - uses: ./.github/workflows/ci-default.yml - - # get the version tag that triggered this workflow - get-version-tag: - # prep version release only if all checks pass - needs: [lint-checks, default-checks] - runs-on: ubuntu-latest - outputs: - git-tag: ${{ steps.git-tag.outputs.tag }} - steps: - - uses: actions/checkout@v4 - - id: git-tag - run: echo "tag=$(git describe --always --tags --match='v*')" >> $GITHUB_OUTPUT - - # build and upload versions of kava for use on internal infrastructure - # configurations for databases, cpu architectures and operating systems - docker: - # only run if all checks pass - needs: get-version-tag - uses: ./.github/workflows/ci-docker.yml - with: - dockerhub-username: kavaops - extra-image-tag: ${{ needs.get-version-tag.outputs.git-tag }} - secrets: inherit diff --git a/.github/workflows/ci-rocksdb-build.yml b/.github/workflows/ci-rocksdb-build.yml deleted file mode 100644 index c760f7b1..00000000 --- a/.github/workflows/ci-rocksdb-build.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: Continuous Integration (Rocksdb Build) - -env: - ROCKSDB_VERSION: v8.10.0 - -on: - workflow_call: -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: checkout repo from current commit - uses: actions/checkout@v4 - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version-file: go.mod - - name: build rocksdb dependency - run: bash ${GITHUB_WORKSPACE}/.github/scripts/install-rocksdb.sh - - name: build application - run: make build COSMOS_BUILD_OPTIONS=rocksdb - test: - runs-on: ubuntu-latest - steps: - - name: install RocksDB dependencies - run: sudo apt-get update - && sudo apt-get install -y git make gcc libgflags-dev libsnappy-dev zlib1g-dev libbz2-dev liblz4-dev libzstd-dev - - name: install RocksDB as shared library - run: git clone https://github.com/facebook/rocksdb.git - && cd rocksdb - && git checkout $ROCKSDB_VERSION - && sudo make -j$(nproc) install-shared - && sudo ldconfig - - name: checkout repo from current commit - uses: actions/checkout@v4 - with: - submodules: true - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version-file: go.mod - - name: run unit tests - run: make test-rocksdb diff --git a/.github/workflows/metric-pipeline.yml b/.github/workflows/metric-pipeline.yml deleted file mode 100644 index 0cd059dc..00000000 --- a/.github/workflows/metric-pipeline.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: Metric Pipeline - -on: - workflow_call: - inputs: - aws-region: - required: true - type: string - metric-name: - required: true - type: string - namespace: - required: true - type: string - secrets: - CI_AWS_KEY_ID: - required: true - CI_AWS_KEY_SECRET: - required: true - -jobs: - metric-pipeline-result: - runs-on: ubuntu-latest - if: always() # always run to capture workflow success or failure - steps: - # Make sure the secrets are stored in you repo settings - - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@v1 - with: - aws-access-key-id: ${{ secrets.CI_AWS_KEY_ID }} - aws-secret-access-key: ${{ secrets.CI_AWS_KEY_SECRET }} - aws-region: ${{ inputs.aws-region }} - - name: Calculate Pipleline Success - # run this action to get the workflow conclusion - # You can get the conclusion via env (env.WORKFLOW_CONCLUSION) - # values: neutral, success, skipped, cancelled, timed_out, - # action_required, failure - uses: technote-space/workflow-conclusion-action@v3 - - name: Metric Pipleline Success - # replace TAG by the latest tag in the repository - uses: ros-tooling/action-cloudwatch-metrics@0.0.5 - with: - metric-value: ${{ env.WORKFLOW_CONCLUSION == 'success' }} - metric-name: ${{ inputs.metric-name }} - namespace: ${{ inputs.namespace }} diff --git a/.github/workflows/proto.yml b/.github/workflows/proto.yml deleted file mode 100644 index b1dc2051..00000000 --- a/.github/workflows/proto.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Protobuf Checks - -on: - workflow_call: - -jobs: - check-proto: - name: "Check Proto" - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version-file: go.mod - - run: go mod download - - run: make install-build-deps - - run: make check-proto-deps - - run: make check-proto-lint - - run: make check-proto-format - - run: make check-proto-breaking-remote - - run: BUF_CHECK_BREAKING_AGAINST_REMOTE="branch=$GITHUB_BASE_REF" make check-proto-breaking-remote - if: github.event_name == 'pull_request' - - run: make check-proto-gen - - run: make check-proto-gen-doc - - run: make check-proto-gen-swagger diff --git a/.gitignore b/.gitignore index 398d9ecb..6c2f05ec 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,9 @@ out # Ignore build cache dir build/.cache +# Ignore make lint cache +build/.golangci-lint + # Ignore installed binaires build/bin @@ -46,3 +49,8 @@ go.work.sum # runtime run + +# contracts +precompiles/interfaces/build +precompiles/interfaces/node_modules +precompiles/interfaces/abis \ No newline at end of file diff --git a/.golangci-version b/.golangci-version new file mode 100644 index 00000000..35345c2f --- /dev/null +++ b/.golangci-version @@ -0,0 +1 @@ +v1.59 diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 00000000..f4f247cd --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,130 @@ +run: + timeout: 20m # set maximum time allowed for the linter to run. If the linting process exceeds this duration, it will be terminated + modules-download-mode: readonly # Ensures that modules are not modified during the linting process + allow-parallel-runners: true # enables parallel execution of linters to speed up linting process + +linters: + disable-all: true + enable: + - asasalint + - asciicheck + - bidichk + - bodyclose + - containedctx + - contextcheck + - decorder + - dogsled + # - dupl + # - dupword + - durationcheck + - errcheck + - errchkjson + - errname + - errorlint + # - exhaustive + - exportloopref + - funlen + - gci + - ginkgolinter + - gocheckcompilerdirectives + # - gochecknoglobals + # - gochecknoinits + - goconst + - gocritic + - godox + - gofmt + # - gofumpt + - goheader + - goimports + - mnd + # - gomodguard + - goprintffuncname + - gosec + - gosimple + - govet + - grouper + - importas + - ineffassign + # - interfacebloat + - lll + - loggercheck + - makezero + - mirror + - misspell + - musttag + # - nakedret + # - nestif + - nilerr + # - nilnil + # - noctx + - nolintlint + # - nonamedreturns + - nosprintfhostport + - prealloc + - predeclared + - promlinter + # - reassign + - revive + - rowserrcheck + - staticcheck + # - stylecheck + - tagalign + # - testpackage + # - thelper + # - tparallel + - typecheck + # - unconvert + - unparam + - unused + # - usestdlibvars + - wastedassign + # - whitespace + - wrapcheck + +issues: + exclude-rules: + # Disable funlen for "func Test..." or func (suite *Suite) Test..." type functions + # These functions tend to be descriptive and exceed length limits. + - source: "^func (\\(.*\\) )?Test" + linters: + - funlen + +linters-settings: + errcheck: + check-blank: true # check for assignments to the blank identifier '_' when errors are returned + check-type-assertions: false # check type assertion + errorlint: + check-generated: false # disabled linting of generated files + default-signifies-exhaustive: false # exhaustive handling of error types + exhaustive: + default-signifies-exhaustive: false # exhaustive handling of error types + gci: + sections: # defines the order of import sections + - standard + - default + - localmodule + goconst: + min-len: 3 # min length for string constants to be checked + min-occurrences: 3 # min occurrences of the same constant before it's flagged + godox: + keywords: # specific keywords to flag for further action + - BUG + - FIXME + - HACK + gosec: + exclude-generated: true + lll: + line-length: 120 + misspell: + locale: US + ignore-words: expect + nolintlint: + allow-leading-space: false + require-explanation: true + require-specific: true + prealloc: + simple: true # enables simple preallocation checks + range-loops: true # enabled preallocation checks in range loops + for-loops: false # disables preallocation checks in for loops + unparam: + check-exported: true # checks exported functions and methods for unused params diff --git a/.mockery.yaml b/.mockery.yaml new file mode 100644 index 00000000..746c20a4 --- /dev/null +++ b/.mockery.yaml @@ -0,0 +1,16 @@ +# Generate EXPECT() methods, type-safe methods to generate call expectations +with-expecter: true + +# Generate mocks in adjacent mocks directory to the interfaces +dir: "{{.InterfaceDir}}/mocks" +mockname: "Mock{{.InterfaceName}}" +outpkg: "mocks" +filename: "Mock{{.InterfaceName}}.go" + +packages: + github.com/0glabs/0g-chain/x/precisebank/types: + # package-specific config + config: + interfaces: + AccountKeeper: + BankKeeper: diff --git a/.tool-versions b/.tool-versions index a0274e41..622b42f0 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,2 +1,2 @@ -golang 1.21 -nodejs 18.16.0 +golang 1.21.9 +nodejs 20.16.0 diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d6b9038..227fbb9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,16 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [v0.26.0] +### Features +- (precisebank) [#1906] Add new `x/precisebank` module with bank decimal extension for EVM usage. +- (cli) [#1922] Add `iavlviewer` CLI command for low-level iavl db debugging. + +### Improvements +- (rocksdb) [#1903] Bump cometbft-db dependency for use with rocksdb v8.10.0 +- (deps) [#1988] Bump cometbft to v0.37.9-kava.1 + +## [v0.26.0] + ### Features - (cli) [#1785] Add `shard` CLI command to support creating partitions of data for standalone nodes @@ -330,6 +340,10 @@ the [changelog](https://github.com/cosmos/cosmos-sdk/blob/v0.38.4/CHANGELOG.md). - [#257](https://github.com/Kava-Labs/kava/pulls/257) Include scripts to run large-scale simulations remotely using aws-batch +[#1988]: https://github.com/Kava-Labs/kava/pull/1988 +[#1922]: https://github.com/Kava-Labs/kava/pull/1922 +[#1906]: https://github.com/Kava-Labs/kava/pull/1906 +[#1903]: https://github.com/Kava-Labs/kava/pull/1903 [#1846]: https://github.com/Kava-Labs/kava/pull/1846 [#1848]: https://github.com/Kava-Labs/kava/pull/1848 [#1839]: https://github.com/Kava-Labs/kava/pull/1839 @@ -392,8 +406,9 @@ the [changelog](https://github.com/cosmos/cosmos-sdk/blob/v0.38.4/CHANGELOG.md). [#750]: https://github.com/Kava-Labs/kava/pull/750 [#751]: https://github.com/Kava-Labs/kava/pull/751 [#780]: https://github.com/Kava-Labs/kava/pull/780 -[unreleased]: https://github.com/Kava-Labs/kava/compare/v0.25.0...HEAD -[v0.25.0]: https://github.com/Kava-Labs/kava/compare/v0.25.0...v0.24.3 +[unreleased]: https://github.com/Kava-Labs/kava/compare/v0.26.0...HEAD +[v0.26.0]: https://github.com/Kava-Labs/kava/compare/v0.25.0...v0.26.0 +[v0.25.0]: https://github.com/Kava-Labs/kava/compare/v0.24.3...v0.25.0 [v0.24.3]: https://github.com/Kava-Labs/kava/compare/v0.24.3...v0.24.1 [v0.24.1]: https://github.com/Kava-Labs/kava/compare/v0.24.1...v0.24.0 [v0.24.0]: https://github.com/Kava-Labs/kava/compare/v0.24.0...v0.23.2 diff --git a/Dockerfile-rocksdb b/Dockerfile-rocksdb index 0a7fc447..d3dfd598 100644 --- a/Dockerfile-rocksdb +++ b/Dockerfile-rocksdb @@ -1,23 +1,6 @@ -FROM golang:1.20-bullseye AS chain-builder +FROM kava/rocksdb:v8.10.1-go1.21 AS kava-builder -# Set up dependencies -RUN apt-get update \ - && apt-get install -y git make gcc libgflags-dev libsnappy-dev zlib1g-dev libbz2-dev liblz4-dev libzstd-dev \ - && rm -rf /var/lib/apt/lists/* - -# Set working directory for the build -WORKDIR /root -# default home directory is /root - -# install rocksdb -ARG rocksdb_version=v8.10.0 -ENV ROCKSDB_VERSION=$rocksdb_version - -RUN git clone https://github.com/facebook/rocksdb.git \ - && cd rocksdb \ - && git checkout $ROCKSDB_VERSION \ - && make -j$(nproc) install-shared \ - && ldconfig +RUN apt-get update WORKDIR /root/0gchain # Copy dependency files first to facilitate dependency caching diff --git a/Dockerfile-rocksdb-base b/Dockerfile-rocksdb-base new file mode 100644 index 00000000..30b3de26 --- /dev/null +++ b/Dockerfile-rocksdb-base @@ -0,0 +1,22 @@ +# published to https://hub.docker.com/repository/docker/kava/rocksdb/tags +# docker buildx build --platform linux/amd64,linux/arm64 -t kava/rocksdb:v8.10.1-go1.21 -f Dockerfile-rocksdb-base . --push +FROM golang:1.21-bullseye + +# Set up dependencies +RUN apt-get update \ + && apt-get install -y git make gcc libgflags-dev libsnappy-dev zlib1g-dev libbz2-dev liblz4-dev libzstd-dev \ + && rm -rf /var/lib/apt/lists/* + +# Set working directory for the build +WORKDIR /root +# default home directory is /root + +# install rocksdb +ARG rocksdb_version=v8.10.0 +ENV ROCKSDB_VERSION=$rocksdb_version + +RUN git clone https://github.com/facebook/rocksdb.git \ + && cd rocksdb \ + && git checkout $ROCKSDB_VERSION \ + && make -j$(nproc) install-shared \ + && ldconfig diff --git a/Makefile b/Makefile index f556645c..9ea5e809 100644 --- a/Makefile +++ b/Makefile @@ -105,6 +105,8 @@ include $(BUILD_DIR)/deps.mk include $(BUILD_DIR)/proto.mk include $(BUILD_DIR)/proto-deps.mk +include $(BUILD_DIR)/lint.mk + #export GO111MODULE = on # process build tags build_tags = netgo @@ -208,6 +210,14 @@ build-release: go.sum build-linux: go.sum LEDGER_ENABLED=false GOOS=linux GOARCH=amd64 $(MAKE) build +# build on rocksdb-backed kava on macOS with shared libs from brew +# this assumes you are on macOS & these deps have been installed with brew: +# rocksdb, snappy, lz4, and zstd +# use like `make build-rocksdb-brew COSMOS_BUILD_OPTIONS=rocksdb` +build-rocksdb-brew: + export CGO_CFLAGS := -I$(shell brew --prefix rocksdb)/include + export CGO_LDFLAGS := -L$(shell brew --prefix rocksdb)/lib -lrocksdb -lstdc++ -lm -lz -L$(shell brew --prefix snappy)/lib -L$(shell brew --prefix lz4)/lib -L$(shell brew --prefix zstd)/lib + install: go.sum $(GO_BIN) install -mod=readonly $(BUILD_FLAGS) $(MAIN_ENTRY) @@ -234,13 +244,6 @@ link-check: # TODO: replace kava in following line with project name liche -r . --exclude "^http://127.*|^https://riot.im/app*|^http://kava-testnet*|^https://testnet-dex*|^https://kava3.data.kava.io*|^https://ipfs.io*|^https://apps.apple.com*|^https://kava.quicksync.io*" - -lint: - golangci-lint run - find . -name '*.go' -type f -not -path "./vendor*" -not -path "*.git*" | xargs gofmt -d -s - $(GO_BIN) mod verify -.PHONY: lint - format: find . -name '*.go' -type f -not -path "./vendor*" -not -path "*.git*" -not -name '*.pb.go' | xargs gofmt -w -s find . -name '*.go' -type f -not -path "./vendor*" -not -path "*.git*" -not -name '*.pb.go' | xargs misspell -w @@ -265,11 +268,11 @@ build-docker-local-0gchain: # Run a 4-node testnet locally localnet-start: build-linux localnet-stop - @if ! [ -f build/node0/kvd/config/genesis.json ]; then docker run --rm -v $(CURDIR)/build:/kvd:Z $(DOCKER_IMAGE_NAME)-node testnet --v 4 -o . --starting-ip-address 192.168.10.2 --keyring-backend=test ; fi - docker-compose up -d + @if ! [ -f build/node0/kvd/config/genesis.json ]; then docker run --rm -v $(CURDIR)/build:/kvd:Z kava/kavanode testnet --v 4 -o . --starting-ip-address 192.168.10.2 --keyring-backend=test ; fi + $(DOCKER) compose up -d localnet-stop: - docker-compose down + $(DOCKER) compose down # Launch a new single validator chain start: @@ -311,12 +314,14 @@ test-basic: test test-e2e: docker-build $(GO_BIN) test -failfast -count=1 -v ./tests/e2e/... +# run interchaintest tests (./tests/e2e-ibc) +test-ibc: docker-build + cd tests/e2e-ibc && KAVA_TAG=local $(GO_BIN) test -timeout 10m . +.PHONY: test-ibc + test: @$(GO_BIN) test $$($(GO_BIN) list ./... | grep -v 'contrib' | grep -v 'tests/e2e') -test-rocksdb: - @go test -tags=rocksdb $(MAIN_ENTRY)/opendb - # Run cli integration tests # `-p 4` to use 4 cores, `-tags cli_test` to tell $(GO_BIN) not to ignore the cli package # These tests use the `kvd` or `kvcli` binaries in the build dir, or in `$BUILDDIR` if that env var is set. @@ -327,6 +332,18 @@ test-cli: build test-migrate: @$(GO_BIN) test -v -count=1 ./migrate/... +# Use the old Apple linker to workaround broken xcode - https://github.com/golang/go/issues/65169 +ifeq ($(OS_FAMILY),Darwin) + FUZZLDFLAGS := -ldflags=-extldflags=-Wl,-ld_classic +endif + +test-fuzz: + @$(GO_BIN) test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzMintCoins ./x/precisebank/keeper + @$(GO_BIN) test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzBurnCoins ./x/precisebank/keeper + @$(GO_BIN) test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzSendCoins ./x/precisebank/keeper + @$(GO_BIN) test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzGenesisStateValidate_NonZeroRemainder ./x/precisebank/types + @$(GO_BIN) test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzGenesisStateValidate_ZeroRemainder ./x/precisebank/types + # Kick start lots of sims on an AWS cluster. # This submits an AWS Batch job to run a lot of sims, each within a docker image. Results are uploaded to S3 start-remote-sims: @@ -337,14 +354,14 @@ start-remote-sims: # submit an array job on AWS Batch, using 1000 seeds, spot instances aws batch submit-job \ -—job-name "master-$(VERSION)" \ - -—job-queue “simulation-1-queue-spot" \ + -—job-queue "simulation-1-queue-spot" \ -—array-properties size=1000 \ -—job-definition $(BINARY_NAME)-sim-master \ -—container-override environment=[{SIM_NAME=master-$(VERSION)}] update-kvtool: git submodule init || true - git submodule update + git submodule update --remote cd tests/e2e/kvtool && make install -.PHONY: all build-linux install clean build test test-cli test-all test-rest test-basic start-remote-sims +.PHONY: all build-linux install build test test-cli test-all test-rest test-basic test-fuzz start-remote-sims diff --git a/README.md b/README.md index 764dccac..85d821f1 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Zero Gravity (0G) is the foundational infrastructure for high-performance dapps It efficiently orchestrates utilization of hardware resources such as storage and compute and software assets such as data and models to handle the scale and complexity of AI workloads. -Continue reading [here](https://0g-doc-new.vercel.app/intro) if you want to learn more about 0G dAIOS and how its various layers enable limitless scalability. +Continue reading [here](https://docs.0g.ai/intro) if you want to learn more about 0G dAIOS and how its various layers enable limitless scalability. ## 0G Product Suite - DA: ultra high-performance data availability layer with KZG and quorum-based DAS @@ -21,17 +21,15 @@ Continue reading [here](https://0g-doc-new.vercel.app/intro) if you want to lear - Network: high-performance, low-latency, and decentralized network ## Documentation -- If you want to build with 0G's network, DA layer, inference serving, or storage SDK, please refer to the [Build with 0G Documentation](https://0g-doc-new.vercel.app/). +- If you want to build with 0G's network, DA layer, inference serving, or storage SDK, please refer to the [Build with 0G Documentation](https://docs.0g.ai/build-with-0g/contracts). -- If you want to run a validator node, DA node, or storage node, please refer to the [Run a Node Documentation](https://0g-doc-new.vercel.app/run-a-node/overview). +- If you want to run a validator node, DA node, or storage node, please refer to the [Run a Node Documentation](https://docs.0g.ai/run-a-node/overview). ## Support and Additional Resources We want to do everything we can to help you be successful while working on your contribution and projects. Here you'll find various resources and communities that may help you complete a project or contribute to 0G. + ### Communities - [0G Telegram](https://t.me/web3_0glabs) -- [0G Discord](https://discord.com/invite/0glabs) - - - +- [0G Discord](https://discord.com/invite/0glabs) \ No newline at end of file diff --git a/app/ante/ante.go b/app/ante/ante.go index abc1db32..e613d16f 100644 --- a/app/ante/ante.go +++ b/app/ante/ante.go @@ -168,6 +168,7 @@ func newEthAnteHandler(options HandlerOptions) sdk.AnteHandler { evmante.NewEthSetUpContextDecorator(options.EvmKeeper), // outermost AnteDecorator. SetUpContext must be called first evmante.NewEthMempoolFeeDecorator(options.EvmKeeper), // Check eth effective gas price against minimal-gas-prices evmante.NewEthValidateBasicDecorator(options.EvmKeeper), + evmante.NewEvmMinGasPriceDecorator(options.EvmKeeper), evmante.NewEthSigVerificationDecorator(options.EvmKeeper), evmante.NewEthAccountVerificationDecorator(options.AccountKeeper, options.EvmKeeper), evmante.NewCanTransferDecorator(options.EvmKeeper), diff --git a/app/ante/eip712_test.go b/app/ante/eip712_test.go index 32809756..d6969504 100644 --- a/app/ante/eip712_test.go +++ b/app/ante/eip712_test.go @@ -405,7 +405,7 @@ func (suite *EIP712TestSuite) TestEIP712Tx() { // usdxToMintAmt: 99, // }, { - name: "fails when convertion more erc20 usdc than balance", + name: "fails when conversion more erc20 usdc than balance", usdcDepositAmt: 51_000, usdxToMintAmt: 100, errMsg: "transfer amount exceeds balance", diff --git a/app/app.go b/app/app.go index 19af3730..0879f353 100644 --- a/app/app.go +++ b/app/app.go @@ -95,6 +95,7 @@ import ( ibckeeper "github.com/cosmos/ibc-go/v7/modules/core/keeper" solomachine "github.com/cosmos/ibc-go/v7/modules/light-clients/06-solomachine" ibctm "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint" + "github.com/ethereum/go-ethereum/core/vm" evmante "github.com/evmos/ethermint/app/ante" ethermintconfig "github.com/evmos/ethermint/server/config" "github.com/evmos/ethermint/x/evm" @@ -109,6 +110,7 @@ import ( chainparams "github.com/0glabs/0g-chain/app/params" "github.com/0glabs/0g-chain/chaincfg" dasignersprecompile "github.com/0glabs/0g-chain/precompiles/dasigners" + stakingprecompile "github.com/0glabs/0g-chain/precompiles/staking" "github.com/0glabs/0g-chain/x/bep3" bep3keeper "github.com/0glabs/0g-chain/x/bep3/keeper" @@ -129,6 +131,9 @@ import ( issuance "github.com/0glabs/0g-chain/x/issuance" issuancekeeper "github.com/0glabs/0g-chain/x/issuance/keeper" issuancetypes "github.com/0glabs/0g-chain/x/issuance/types" + "github.com/0glabs/0g-chain/x/precisebank" + precisebankkeeper "github.com/0glabs/0g-chain/x/precisebank/keeper" + precisebanktypes "github.com/0glabs/0g-chain/x/precisebank/types" pricefeed "github.com/0glabs/0g-chain/x/pricefeed" pricefeedkeeper "github.com/0glabs/0g-chain/x/pricefeed/keeper" pricefeedtypes "github.com/0glabs/0g-chain/x/pricefeed/types" @@ -136,7 +141,6 @@ import ( validatorvestingrest "github.com/0glabs/0g-chain/x/validator-vesting/client/rest" validatorvestingtypes "github.com/0glabs/0g-chain/x/validator-vesting/types" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/vm" ) var ( @@ -178,6 +182,7 @@ var ( validatorvesting.AppModuleBasic{}, evmutil.AppModuleBasic{}, mint.AppModuleBasic{}, + precisebank.AppModuleBasic{}, council.AppModuleBasic{}, dasigners.AppModuleBasic{}, consensus.AppModuleBasic{}, @@ -199,6 +204,7 @@ var ( issuancetypes.ModuleAccountName: {authtypes.Minter, authtypes.Burner}, bep3types.ModuleName: {authtypes.Burner, authtypes.Minter}, minttypes.ModuleName: {authtypes.Minter}, + precisebanktypes.ModuleName: {authtypes.Minter, authtypes.Burner}, // used for reserve account to back fractional amounts } ) @@ -268,6 +274,7 @@ type App struct { mintKeeper mintkeeper.Keeper dasignersKeeper dasignerskeeper.Keeper consensusParamsKeeper consensusparamkeeper.Keeper + precisebankKeeper precisebankkeeper.Keeper // make scoped keepers public for test purposes ScopedIBCKeeper capabilitykeeper.ScopedKeeper @@ -318,7 +325,7 @@ func NewApp( counciltypes.StoreKey, dasignerstypes.StoreKey, vestingtypes.StoreKey, - consensusparamtypes.StoreKey, crisistypes.StoreKey, + consensusparamtypes.StoreKey, crisistypes.StoreKey, precisebanktypes.StoreKey, ibcwasmtypes.StoreKey, ) tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey, evmtypes.TransientKey, feemarkettypes.TransientKey) @@ -482,26 +489,41 @@ func NewApp( app.accountKeeper, ) - evmBankKeeper := evmutilkeeper.NewEvmBankKeeper(app.evmutilKeeper, app.bankKeeper, app.accountKeeper) + app.precisebankKeeper = precisebankkeeper.NewKeeper( + app.appCodec, + keys[precisebanktypes.StoreKey], + app.bankKeeper, + app.accountKeeper, + ) + // dasigners keeper app.dasignersKeeper = dasignerskeeper.NewKeeper(keys[dasignerstypes.StoreKey], appCodec, app.stakingKeeper, govAuthAddrStr) // precopmiles precompiles := make(map[common.Address]vm.PrecompiledContract) + // dasigners daSignersPrecompile, err := dasignersprecompile.NewDASignersPrecompile(app.dasignersKeeper) if err != nil { - panic("initialize precompile failed") + panic(fmt.Sprintf("initialize dasigners precompile failed: %v", err)) } precompiles[daSignersPrecompile.Address()] = daSignersPrecompile - // evm keeper + // staking + stakingPrecompile, err := stakingprecompile.NewStakingPrecompile(app.stakingKeeper) + if err != nil { + panic(fmt.Sprintf("initialize staking precompile failed: %v", err)) + } + precompiles[stakingPrecompile.Address()] = stakingPrecompile + app.evmKeeper = evmkeeper.NewKeeper( appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey], govAuthAddr, - app.accountKeeper, evmBankKeeper, app.stakingKeeper, app.feeMarketKeeper, + app.accountKeeper, + app.precisebankKeeper, // x/precisebank in place of x/bank + app.stakingKeeper, + app.feeMarketKeeper, options.EVMTrace, evmSubspace, precompiles, ) - app.evmutilKeeper.SetEvmKeeper(app.evmKeeper) // It's important to note that the PFM Keeper must be initialized before the Transfer Keeper @@ -669,6 +691,7 @@ func NewApp( evmutil.NewAppModule(app.evmutilKeeper, app.bankKeeper, app.accountKeeper), // nil InflationCalculationFn, use SDK's default inflation function mint.NewAppModule(appCodec, app.mintKeeper, app.accountKeeper, nil, mintSubspace), + precisebank.NewAppModule(app.precisebankKeeper, app.bankKeeper, app.accountKeeper), council.NewAppModule(app.CouncilKeeper), ibcwasm.NewAppModule(app.ibcWasmClientKeeper), dasigners.NewAppModule(app.dasignersKeeper, *app.stakingKeeper), @@ -716,6 +739,7 @@ func NewApp( counciltypes.ModuleName, consensusparamtypes.ModuleName, packetforwardtypes.ModuleName, + precisebanktypes.ModuleName, ibcwasmtypes.ModuleName, dasignerstypes.ModuleName, ) @@ -752,6 +776,7 @@ func NewApp( counciltypes.ModuleName, consensusparamtypes.ModuleName, packetforwardtypes.ModuleName, + precisebanktypes.ModuleName, ibcwasmtypes.ModuleName, dasignerstypes.ModuleName, ) @@ -786,7 +811,8 @@ func NewApp( counciltypes.ModuleName, consensusparamtypes.ModuleName, packetforwardtypes.ModuleName, - crisistypes.ModuleName, // runs the invariants at genesis, should run after other modules + precisebanktypes.ModuleName, // Must be run after x/bank to verify reserve balance + crisistypes.ModuleName, // runs the invariants at genesis, should run after other modules ibcwasmtypes.ModuleName, dasignerstypes.ModuleName, ) diff --git a/app/params/doc.go b/app/params/doc.go index 5eb101c1..afc65e8c 100644 --- a/app/params/doc.go +++ b/app/params/doc.go @@ -3,9 +3,9 @@ Package params defines the simulation parameters for the 0gChain app. It contains the default weights used for each transaction used on the module's simulation. These weights define the chance for a transaction to be simulated at -any gived operation. +any given operation. -You can repace the default values for the weights by providing a params.json +You can replace the default values for the weights by providing a params.json file with the weights defined for each of the transaction operations: { diff --git a/app/tally_handler_test.go b/app/tally_handler_test.go index 80894528..7e272b3f 100644 --- a/app/tally_handler_test.go +++ b/app/tally_handler_test.go @@ -130,7 +130,7 @@ func (suite *tallyHandlerSuite) TestTallyOutcomes() { passes, burns, tally := suite.tallier.Tally(suite.ctx, proposal) suite.Falsef(passes, "expected proposal to fail, tally: %v", tally) - suite.Truef(burns, "expected desposit to be burned, tally: %v", tally) + suite.Truef(burns, "expected deposit to be burned, tally: %v", tally) }) suite.Run("VetoedFails", func() { suite.SetupTest() @@ -145,7 +145,7 @@ func (suite *tallyHandlerSuite) TestTallyOutcomes() { passes, burns, tally := suite.tallier.Tally(suite.ctx, proposal) suite.Falsef(passes, "expected proposal to fail, tally: %v", tally) - suite.Truef(burns, "expected desposit to be burned, tally: %v", tally) + suite.Truef(burns, "expected deposit to be burned, tally: %v", tally) }) suite.Run("UnvetoedAndYesAboveThresholdPasses", func() { suite.SetupTest() @@ -162,7 +162,7 @@ func (suite *tallyHandlerSuite) TestTallyOutcomes() { passes, burns, tally := suite.tallier.Tally(suite.ctx, proposal) suite.Truef(passes, "expected proposal to pass, tally: %v", tally) - suite.Falsef(burns, "expected desposit to not burn, tally: %v", tally) + suite.Falsef(burns, "expected deposit to not burn, tally: %v", tally) }) suite.Run("UnvetoedAndYesBelowThresholdFails", func() { suite.SetupTest() @@ -179,7 +179,7 @@ func (suite *tallyHandlerSuite) TestTallyOutcomes() { passes, burns, tally := suite.tallier.Tally(suite.ctx, proposal) suite.Falsef(passes, "expected proposal to pass, tally: %v", tally) - suite.Falsef(burns, "expected desposit to not burn, tally: %v", tally) + suite.Falsef(burns, "expected deposit to not burn, tally: %v", tally) }) suite.Run("NotEnoughStakeFails", func() { suite.SetupTest() @@ -191,7 +191,7 @@ func (suite *tallyHandlerSuite) TestTallyOutcomes() { passes, burns, tally := suite.tallier.Tally(suite.ctx, proposal) suite.Falsef(passes, "expected proposal to pass, tally: %v", tally) - suite.Falsef(burns, "expected desposit to not burn, tally: %v", tally) + suite.Falsef(burns, "expected deposit to not burn, tally: %v", tally) }) suite.Run("UnvetoedAndAllAbstainedFails", func() { suite.SetupTest() @@ -204,7 +204,7 @@ func (suite *tallyHandlerSuite) TestTallyOutcomes() { passes, burns, tally := suite.tallier.Tally(suite.ctx, proposal) suite.Falsef(passes, "expected proposal to pass, tally: %v", tally) - suite.Falsef(burns, "expected desposit to not burn, tally: %v", tally) + suite.Falsef(burns, "expected deposit to not burn, tally: %v", tally) }) } diff --git a/app/test_common.go b/app/test_common.go index 5962a72e..b822ddd2 100644 --- a/app/test_common.go +++ b/app/test_common.go @@ -47,6 +47,7 @@ import ( committeekeeper "github.com/0glabs/0g-chain/x/committee/keeper" evmutilkeeper "github.com/0glabs/0g-chain/x/evmutil/keeper" issuancekeeper "github.com/0glabs/0g-chain/x/issuance/keeper" + precisebankkeeper "github.com/0glabs/0g-chain/x/precisebank/keeper" pricefeedkeeper "github.com/0glabs/0g-chain/x/pricefeed/keeper" ) @@ -99,28 +100,33 @@ func NewTestAppFromSealed() TestApp { } // nolint -func (tApp TestApp) GetAccountKeeper() authkeeper.AccountKeeper { return tApp.accountKeeper } -func (tApp TestApp) GetBankKeeper() bankkeeper.Keeper { return tApp.bankKeeper } -func (tApp TestApp) GetMintKeeper() mintkeeper.Keeper { return tApp.mintKeeper } -func (tApp TestApp) GetStakingKeeper() *stakingkeeper.Keeper { return tApp.stakingKeeper } -func (tApp TestApp) GetSlashingKeeper() slashingkeeper.Keeper { return tApp.slashingKeeper } -func (tApp TestApp) GetDistrKeeper() distkeeper.Keeper { return tApp.distrKeeper } -func (tApp TestApp) GetGovKeeper() govkeeper.Keeper { return tApp.govKeeper } -func (tApp TestApp) GetCrisisKeeper() crisiskeeper.Keeper { return tApp.crisisKeeper } -func (tApp TestApp) GetParamsKeeper() paramskeeper.Keeper { return tApp.paramsKeeper } -func (tApp TestApp) GetIssuanceKeeper() issuancekeeper.Keeper { return tApp.issuanceKeeper } -func (tApp TestApp) GetBep3Keeper() bep3keeper.Keeper { return tApp.bep3Keeper } -func (tApp TestApp) GetPriceFeedKeeper() pricefeedkeeper.Keeper { return tApp.pricefeedKeeper } -func (tApp TestApp) GetCommitteeKeeper() committeekeeper.Keeper { return tApp.committeeKeeper } -func (tApp TestApp) GetEvmutilKeeper() evmutilkeeper.Keeper { return tApp.evmutilKeeper } -func (tApp TestApp) GetEvmKeeper() *evmkeeper.Keeper { return tApp.evmKeeper } -func (tApp TestApp) GetFeeMarketKeeper() feemarketkeeper.Keeper { return tApp.feeMarketKeeper } -func (tApp TestApp) GetDASignersKeeper() dasignerskeeper.Keeper { return tApp.dasignersKeeper } +func (tApp TestApp) GetAccountKeeper() authkeeper.AccountKeeper { return tApp.accountKeeper } +func (tApp TestApp) GetBankKeeper() bankkeeper.Keeper { return tApp.bankKeeper } +func (tApp TestApp) GetMintKeeper() mintkeeper.Keeper { return tApp.mintKeeper } +func (tApp TestApp) GetStakingKeeper() *stakingkeeper.Keeper { return tApp.stakingKeeper } +func (tApp TestApp) GetSlashingKeeper() slashingkeeper.Keeper { return tApp.slashingKeeper } +func (tApp TestApp) GetDistrKeeper() distkeeper.Keeper { return tApp.distrKeeper } +func (tApp TestApp) GetGovKeeper() govkeeper.Keeper { return tApp.govKeeper } +func (tApp TestApp) GetCrisisKeeper() crisiskeeper.Keeper { return tApp.crisisKeeper } +func (tApp TestApp) GetParamsKeeper() paramskeeper.Keeper { return tApp.paramsKeeper } +func (tApp TestApp) GetIssuanceKeeper() issuancekeeper.Keeper { return tApp.issuanceKeeper } +func (tApp TestApp) GetBep3Keeper() bep3keeper.Keeper { return tApp.bep3Keeper } +func (tApp TestApp) GetPriceFeedKeeper() pricefeedkeeper.Keeper { return tApp.pricefeedKeeper } +func (tApp TestApp) GetCommitteeKeeper() committeekeeper.Keeper { return tApp.committeeKeeper } +func (tApp TestApp) GetEvmutilKeeper() evmutilkeeper.Keeper { return tApp.evmutilKeeper } +func (tApp TestApp) GetEvmKeeper() *evmkeeper.Keeper { return tApp.evmKeeper } +func (tApp TestApp) GetFeeMarketKeeper() feemarketkeeper.Keeper { return tApp.feeMarketKeeper } +func (tApp TestApp) GetDASignersKeeper() dasignerskeeper.Keeper { return tApp.dasignersKeeper } +func (tApp TestApp) GetPrecisebankKeeper() precisebankkeeper.Keeper { return tApp.precisebankKeeper } func (tApp TestApp) GetKVStoreKey(key string) *storetypes.KVStoreKey { return tApp.keys[key] } +func (tApp TestApp) GetBlockedMaccAddrs() map[string]bool { + return tApp.loadBlockedMaccAddrs() +} + // LegacyAmino returns the app's amino codec. func (app *App) LegacyAmino() *codec.LegacyAmino { return app.legacyAmino @@ -465,7 +471,7 @@ func (tApp TestApp) SetInflation(ctx sdk.Context, value sdk.Dec) { mk.SetParams(ctx, mintParams) } -// GeneratePrivKeyAddressPairsFromRand generates (deterministically) a total of n private keys and addresses. +// GeneratePrivKeyAddressPairs generates (deterministically) a total of n private keys and addresses. func GeneratePrivKeyAddressPairs(n int) (keys []cryptotypes.PrivKey, addrs []sdk.AccAddress) { r := rand.New(rand.NewSource(12345)) // make the generation deterministic keys = make([]cryptotypes.PrivKey, n) diff --git a/app/upgrades.go b/app/upgrades.go index ea5f3fc9..cf486d04 100644 --- a/app/upgrades.go +++ b/app/upgrades.go @@ -3,13 +3,21 @@ package app import ( "fmt" + sdkmath "cosmossdk.io/math" + + evmutilkeeper "github.com/0glabs/0g-chain/x/evmutil/keeper" + evmutiltypes "github.com/0glabs/0g-chain/x/evmutil/types" + precisebankkeeper "github.com/0glabs/0g-chain/x/precisebank/keeper" + precisebanktypes "github.com/0glabs/0g-chain/x/precisebank/types" + storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" ) const ( - UpgradeName_Testnet = "v0.3.1" + UpgradeName_Testnet = "v0.4.0" ) // RegisterUpgradeHandlers registers the upgrade handlers for the app. @@ -18,6 +26,24 @@ func (app App) RegisterUpgradeHandlers() { UpgradeName_Testnet, upgradeHandler(app, UpgradeName_Testnet), ) + + upgradeInfo, err := app.upgradeKeeper.ReadUpgradeInfoFromDisk() + if err != nil { + panic(err) + } + + doUpgrade := upgradeInfo.Name == UpgradeName_Testnet + + if doUpgrade && !app.upgradeKeeper.IsSkipHeight(upgradeInfo.Height) { + storeUpgrades := storetypes.StoreUpgrades{ + Added: []string{ + precisebanktypes.ModuleName, + }, + } + + // configure store loader that checks if version == upgradeHeight and applies store upgrades + app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgradeInfo.Height, &storeUpgrades)) + } } // upgradeHandler returns an UpgradeHandler for the given upgrade parameters. @@ -30,13 +56,213 @@ func upgradeHandler( plan upgradetypes.Plan, fromVM module.VersionMap, ) (module.VersionMap, error) { - app.Logger().Info(fmt.Sprintf("running %s upgrade handler", name)) + logger := app.Logger() + logger.Info(fmt.Sprintf("running %s upgrade handler", name)) - params := app.mintKeeper.GetParams(ctx) - params.MintDenom = "ua0gi" - app.mintKeeper.SetParams(ctx, params) + // Run migrations for all modules and return new consensus version map. + versionMap, err := app.mm.RunMigrations(ctx, app.configurator, fromVM) + if err != nil { + return nil, err + } - // run migrations for all modules and return new consensus version map - return app.mm.RunMigrations(ctx, app.configurator, fromVM) + logger.Info("completed store migrations") + + // Migration of fractional balances from x/evmutil to x/precisebank + if err := MigrateEvmutilToPrecisebank( + ctx, + app.accountKeeper, + app.bankKeeper, + app.evmutilKeeper, + app.precisebankKeeper, + ); err != nil { + return nil, err + } + + logger.Info("completed x/evmutil to x/precisebank migration") + + return versionMap, nil } } + +// MigrateEvmutilToPrecisebank migrates all required state from x/evmutil to +// x/precisebank and ensures the resulting state is correct. +// This migrates the following state: +// - Fractional balances +// - Fractional balance reserve +// Initializes the following state in x/precisebank: +// - Remainder amount +func MigrateEvmutilToPrecisebank( + ctx sdk.Context, + accountKeeper evmutiltypes.AccountKeeper, + bankKeeper bankkeeper.Keeper, + evmutilKeeper evmutilkeeper.Keeper, + precisebankKeeper precisebankkeeper.Keeper, +) error { + logger := ctx.Logger() + + aggregateSum, err := TransferFractionalBalances( + ctx, + evmutilKeeper, + precisebankKeeper, + ) + if err != nil { + return fmt.Errorf("fractional balances transfer: %w", err) + } + logger.Info( + "fractional balances transferred from x/evmutil to x/precisebank", + "aggregate sum", aggregateSum, + ) + + remainder := InitializeRemainder(ctx, precisebankKeeper, aggregateSum) + logger.Info("remainder amount initialized in x/precisebank", "remainder", remainder) + + // Migrate fractional balances, reserve, and ensure reserve fully backs all + // fractional balances. + if err := TransferFractionalBalanceReserve( + ctx, + accountKeeper, + bankKeeper, + precisebankKeeper, + ); err != nil { + return fmt.Errorf("reserve transfer: %w", err) + } + + return nil +} + +// TransferFractionalBalances migrates fractional balances from x/evmutil to +// x/precisebank. It sets the fractional balance in x/precisebank and deletes +// the account from x/evmutil. Returns the aggregate sum of all fractional +// balances. +func TransferFractionalBalances( + ctx sdk.Context, + evmutilKeeper evmutilkeeper.Keeper, + precisebankKeeper precisebankkeeper.Keeper, +) (sdkmath.Int, error) { + aggregateSum := sdkmath.ZeroInt() + + var iterErr error + + evmutilKeeper.IterateAllAccounts(ctx, func(acc evmutiltypes.Account) bool { + // Set account balance in x/precisebank + precisebankKeeper.SetFractionalBalance(ctx, acc.Address, acc.Balance) + + // Delete account from x/evmutil + iterErr := evmutilKeeper.SetAccount(ctx, evmutiltypes.Account{ + Address: acc.Address, + // Set balance to 0 to delete it + Balance: sdkmath.ZeroInt(), + }) + + // Halt iteration if there was an error + if iterErr != nil { + return true + } + + // Aggregate sum of all fractional balances + aggregateSum = aggregateSum.Add(acc.Balance) + + // Continue iterating + return false + }) + + return aggregateSum, iterErr +} + +// InitializeRemainder initializes the remainder amount in x/precisebank. It +// calculates the remainder amount that is needed to ensure that the sum of all +// fractional balances is a multiple of the conversion factor. The remainder +// amount is stored in the store and returned. +func InitializeRemainder( + ctx sdk.Context, + precisebankKeeper precisebankkeeper.Keeper, + aggregateSum sdkmath.Int, +) sdkmath.Int { + // Extra fractional coins that exceed the conversion factor. + // This extra + remainder should equal the conversion factor to ensure + // (sum(fBalances) + remainder) % conversionFactor = 0 + extraFractionalAmount := aggregateSum.Mod(precisebanktypes.ConversionFactor()) + remainder := precisebanktypes.ConversionFactor(). + Sub(extraFractionalAmount). + // Mod conversion factor to ensure remainder is valid. + // If extraFractionalAmount is a multiple of conversion factor, the + // remainder is 0. + Mod(precisebanktypes.ConversionFactor()) + + // Panics if the remainder is invalid. In a correct chain state and only + // mint/burns due to transfers, this would be 0. + precisebankKeeper.SetRemainderAmount(ctx, remainder) + + return remainder +} + +// TransferFractionalBalanceReserve migrates the fractional balance reserve from +// x/evmutil to x/precisebank. It transfers the reserve balance from x/evmutil +// to x/precisebank and ensures that the reserve fully backs all fractional +// balances. It mints or burns coins to back the fractional balances exactly. +func TransferFractionalBalanceReserve( + ctx sdk.Context, + accountKeeper evmutiltypes.AccountKeeper, + bankKeeper bankkeeper.Keeper, + precisebankKeeper precisebankkeeper.Keeper, +) error { + logger := ctx.Logger() + + // Transfer x/evmutil reserve to x/precisebank. + evmutilAddr := accountKeeper.GetModuleAddress(evmutiltypes.ModuleName) + reserveBalance := bankKeeper.GetBalance(ctx, evmutilAddr, precisebanktypes.IntegerCoinDenom) + + if err := bankKeeper.SendCoinsFromModuleToModule( + ctx, + evmutiltypes.ModuleName, // from x/evmutil + precisebanktypes.ModuleName, // to x/precisebank + sdk.NewCoins(reserveBalance), + ); err != nil { + return fmt.Errorf("failed to transfer reserve from x/evmutil to x/precisebank: %w", err) + } + + logger.Info(fmt.Sprintf("transferred reserve balance: %s", reserveBalance)) + + // Ensure x/precisebank reserve fully backs all fractional balances. + totalFractionalBalances := precisebankKeeper.GetTotalSumFractionalBalances(ctx) + + // Does NOT ensure state is correct, total fractional balances should be a + // multiple of conversion factor but is not guaranteed due to the remainder. + // Remainder initialization is handled by InitializeRemainder. + + // Determine how much the reserve is off by, e.g. unbacked amount + expectedReserveBalance := totalFractionalBalances.Quo(precisebanktypes.ConversionFactor()) + + // If there is a remainder (totalFractionalBalances % conversionFactor != 0), + // then expectedReserveBalance is rounded up to the nearest integer. + if totalFractionalBalances.Mod(precisebanktypes.ConversionFactor()).IsPositive() { + expectedReserveBalance = expectedReserveBalance.Add(sdkmath.OneInt()) + } + + unbackedAmount := expectedReserveBalance.Sub(reserveBalance.Amount) + logger.Info(fmt.Sprintf("total account fractional balances: %s", totalFractionalBalances)) + + // Three possible cases: + // 1. Reserve is not enough, mint coins to back the fractional balances + // 2. Reserve is too much, burn coins to back the fractional balances exactly + // 3. Reserve is exactly enough, no action needed + if unbackedAmount.IsPositive() { + coins := sdk.NewCoins(sdk.NewCoin(precisebanktypes.IntegerCoinDenom, unbackedAmount)) + if err := bankKeeper.MintCoins(ctx, precisebanktypes.ModuleName, coins); err != nil { + return fmt.Errorf("failed to mint extra reserve coins: %w", err) + } + + logger.Info(fmt.Sprintf("unbacked amount minted to reserve: %s", unbackedAmount)) + } else if unbackedAmount.IsNegative() { + coins := sdk.NewCoins(sdk.NewCoin(precisebanktypes.IntegerCoinDenom, unbackedAmount.Neg())) + if err := bankKeeper.BurnCoins(ctx, precisebanktypes.ModuleName, coins); err != nil { + return fmt.Errorf("failed to burn extra reserve coins: %w", err) + } + + logger.Info(fmt.Sprintf("extra reserve amount burned: %s", unbackedAmount.Neg())) + } else { + logger.Info("reserve exactly backs fractional balances, no mint/burn needed") + } + + return nil +} diff --git a/app/upgrades_test.go b/app/upgrades_test.go new file mode 100644 index 00000000..d4783904 --- /dev/null +++ b/app/upgrades_test.go @@ -0,0 +1,434 @@ +package app_test + +import ( + "strconv" + "testing" + "time" + + sdkmath "cosmossdk.io/math" + "github.com/0glabs/0g-chain/app" + evmutiltypes "github.com/0glabs/0g-chain/x/evmutil/types" + precisebankkeeper "github.com/0glabs/0g-chain/x/precisebank/keeper" + precisebanktypes "github.com/0glabs/0g-chain/x/precisebank/types" + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +func TestMigrateEvmutilToPrecisebank(t *testing.T) { + // Full test case with all components together + tests := []struct { + name string + initialReserve sdkmath.Int + fractionalBalances []sdkmath.Int + }{ + { + "no fractional balances", + sdkmath.NewInt(0), + []sdkmath.Int{}, + }, + { + "sufficient reserve, 0 remainder", + // Accounts adding up to 2 int units, same as reserve + sdkmath.NewInt(2), + []sdkmath.Int{ + precisebanktypes.ConversionFactor().QuoRaw(2), + precisebanktypes.ConversionFactor().QuoRaw(2), + precisebanktypes.ConversionFactor().QuoRaw(2), + precisebanktypes.ConversionFactor().QuoRaw(2), + }, + }, + { + "insufficient reserve, 0 remainder", + // Accounts adding up to 2 int units, but only 1 int unit in reserve + sdkmath.NewInt(1), + []sdkmath.Int{ + precisebanktypes.ConversionFactor().QuoRaw(2), + precisebanktypes.ConversionFactor().QuoRaw(2), + precisebanktypes.ConversionFactor().QuoRaw(2), + precisebanktypes.ConversionFactor().QuoRaw(2), + }, + }, + { + "excess reserve, 0 remainder", + // Accounts adding up to 2 int units, but 3 int unit in reserve + sdkmath.NewInt(3), + []sdkmath.Int{ + precisebanktypes.ConversionFactor().QuoRaw(2), + precisebanktypes.ConversionFactor().QuoRaw(2), + precisebanktypes.ConversionFactor().QuoRaw(2), + precisebanktypes.ConversionFactor().QuoRaw(2), + }, + }, + { + "sufficient reserve, non-zero remainder", + // Accounts adding up to 1.5 int units, same as reserve + sdkmath.NewInt(2), + []sdkmath.Int{ + precisebanktypes.ConversionFactor().QuoRaw(2), + precisebanktypes.ConversionFactor().QuoRaw(2), + precisebanktypes.ConversionFactor().QuoRaw(2), + }, + }, + { + "insufficient reserve, non-zero remainder", + // Accounts adding up to 1.5 int units, less than reserve, + // Reserve should be 2 and remainder 0.5 + sdkmath.NewInt(1), + []sdkmath.Int{ + precisebanktypes.ConversionFactor().QuoRaw(2), + precisebanktypes.ConversionFactor().QuoRaw(2), + precisebanktypes.ConversionFactor().QuoRaw(2), + }, + }, + { + "excess reserve, non-zero remainder", + // Accounts adding up to 1.5 int units, 3 int units in reserve + sdkmath.NewInt(3), + []sdkmath.Int{ + precisebanktypes.ConversionFactor().QuoRaw(2), + precisebanktypes.ConversionFactor().QuoRaw(2), + precisebanktypes.ConversionFactor().QuoRaw(2), + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tApp := app.NewTestApp() + tApp.InitializeFromGenesisStates() + ctx := tApp.NewContext(true, tmproto.Header{Height: 1, Time: time.Now()}) + + ak := tApp.GetAccountKeeper() + bk := tApp.GetBankKeeper() + evmuk := tApp.GetEvmutilKeeper() + pbk := tApp.GetPrecisebankKeeper() + + reserveCoin := sdk.NewCoin(precisebanktypes.IntegerCoinDenom, tt.initialReserve) + err := bk.MintCoins(ctx, evmutiltypes.ModuleName, sdk.NewCoins(reserveCoin)) + require.NoError(t, err) + + oldReserveAddr := tApp.GetAccountKeeper().GetModuleAddress(evmutiltypes.ModuleName) + newReserveAddr := tApp.GetAccountKeeper().GetModuleAddress(precisebanktypes.ModuleName) + + // Double check balances + oldReserveBalance := bk.GetBalance(ctx, oldReserveAddr, precisebanktypes.IntegerCoinDenom) + newReserveBalance := bk.GetBalance(ctx, newReserveAddr, precisebanktypes.IntegerCoinDenom) + + require.Equal(t, tt.initialReserve, oldReserveBalance.Amount, "initial x/evmutil reserve balance") + require.True(t, newReserveBalance.IsZero(), "empty initial new reserve") + + // Set accounts + for i, balance := range tt.fractionalBalances { + addr := sdk.AccAddress([]byte(strconv.Itoa(i))) + + err := evmuk.SetBalance(ctx, addr, balance) + require.NoError(t, err) + } + + // Run full x/evmutil -> x/precisebank migration + err = app.MigrateEvmutilToPrecisebank( + ctx, + ak, + bk, + evmuk, + pbk, + ) + require.NoError(t, err) + + // Check old reserve is empty + oldReserveBalanceAfter := bk.GetBalance(ctx, oldReserveAddr, precisebanktypes.IntegerCoinDenom) + require.True(t, oldReserveBalanceAfter.IsZero(), "old reserve should be empty") + + // Check new reserve fully backs fractional balances + newReserveBalanceAfter := bk.GetBalance(ctx, newReserveAddr, precisebanktypes.IntegerCoinDenom) + fractionalBalanceTotal := pbk.GetTotalSumFractionalBalances(ctx) + remainder := pbk.GetRemainderAmount(ctx) + + expectedReserveBal := fractionalBalanceTotal.Add(remainder) + require.Equal( + t, + expectedReserveBal, + newReserveBalanceAfter.Amount.Mul(precisebanktypes.ConversionFactor()), + "new reserve should equal total fractional balances", + ) + + // Check balances are deleted in evmutil and migrated to precisebank + for i := range tt.fractionalBalances { + addr := sdk.AccAddress([]byte(strconv.Itoa(i))) + acc := evmuk.GetAccount(ctx, addr) + require.Nil(t, acc, "account should be deleted") + + balance := pbk.GetFractionalBalance(ctx, addr) + require.Equal(t, tt.fractionalBalances[i], balance, "balance should be migrated") + } + + // Checks balances valid and remainder + res, stop := precisebankkeeper.AllInvariants(pbk)(ctx) + require.Falsef(t, stop, "invariants should pass: %s", res) + }) + } +} + +func TestTransferFractionalBalances(t *testing.T) { + tests := []struct { + name string + fractionalBalances []sdkmath.Int + }{ + { + "no fractional balances", + []sdkmath.Int{}, + }, + { + "balanced fractional balances", + []sdkmath.Int{ + // 4 accounts + precisebanktypes.ConversionFactor().QuoRaw(2), + precisebanktypes.ConversionFactor().QuoRaw(2), + precisebanktypes.ConversionFactor().QuoRaw(2), + precisebanktypes.ConversionFactor().QuoRaw(2), + }, + }, + { + "unbalanced balances", + []sdkmath.Int{ + // 3 accounts + precisebanktypes.ConversionFactor().QuoRaw(2), + precisebanktypes.ConversionFactor().QuoRaw(2), + precisebanktypes.ConversionFactor().QuoRaw(2), + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tApp := app.NewTestApp() + tApp.InitializeFromGenesisStates() + ctx := tApp.NewContext(true, tmproto.Header{Height: 1, Time: time.Now()}) + + evmutilk := tApp.GetEvmutilKeeper() + pbk := tApp.GetPrecisebankKeeper() + + for i, balance := range tt.fractionalBalances { + addr := sdk.AccAddress([]byte(strconv.Itoa(i))) + + err := evmutilk.SetBalance(ctx, addr, balance) + require.NoError(t, err) + } + + // Run balance transfer + aggregateSum, err := app.TransferFractionalBalances( + ctx, + evmutilk, + pbk, + ) + require.NoError(t, err) + + // Check balances are deleted in evmutil and migrated to precisebank + sum := sdkmath.ZeroInt() + for i := range tt.fractionalBalances { + sum = sum.Add(tt.fractionalBalances[i]) + + addr := sdk.AccAddress([]byte(strconv.Itoa(i))) + acc := evmutilk.GetAccount(ctx, addr) + require.Nil(t, acc, "account should be deleted") + + balance := pbk.GetFractionalBalance(ctx, addr) + require.Equal(t, tt.fractionalBalances[i], balance, "balance should be migrated") + } + + require.Equal(t, sum, aggregateSum, "aggregate sum should be correct") + }) + } +} + +func TestInitializeRemainder(t *testing.T) { + tests := []struct { + name string + giveAggregateSum sdkmath.Int + wantRemainder sdkmath.Int + }{ + { + "0 remainder, 1ukava", + precisebanktypes.ConversionFactor(), + sdkmath.NewInt(0), + }, + { + "0 remainder, multiple ukava", + precisebanktypes.ConversionFactor().MulRaw(5), + sdkmath.NewInt(0), + }, + { + "non-zero remainder, min", + precisebanktypes.ConversionFactor().SubRaw(1), + sdkmath.NewInt(1), + }, + { + "non-zero remainder, max", + sdkmath.NewInt(1), + precisebanktypes.ConversionFactor().SubRaw(1), + }, + { + "non-zero remainder, half", + precisebanktypes.ConversionFactor().QuoRaw(2), + precisebanktypes.ConversionFactor().QuoRaw(2), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tApp := app.NewTestApp() + tApp.InitializeFromGenesisStates() + + pbk := tApp.GetPrecisebankKeeper() + + ctx := tApp.NewContext(true, tmproto.Header{Height: 1, Time: time.Now()}) + + remainder := app.InitializeRemainder( + ctx, + tApp.GetPrecisebankKeeper(), + tt.giveAggregateSum, + ) + require.Equal(t, tt.wantRemainder, remainder) + + // Check actual state + remainderAfter := pbk.GetRemainderAmount(ctx) + require.Equal(t, tt.wantRemainder, remainderAfter) + + // Not checking invariants here since it requires actual balance state + aggregateSumWithRemainder := tt.giveAggregateSum.Add(remainder) + require.True( + t, + aggregateSumWithRemainder. + Mod(precisebanktypes.ConversionFactor()). + IsZero(), + "remainder + aggregate sum should be a multiple of the conversion factor", + ) + }) + } +} + +func TestTransferFractionalBalanceReserve(t *testing.T) { + tests := []struct { + name string + initialReserve sdk.Coin + fractionalBalances []sdkmath.Int + }{ + { + "balanced reserve, no remainder", + sdk.NewCoin(precisebanktypes.IntegerCoinDenom, sdk.NewInt(1)), + []sdkmath.Int{ + // 2 accounts + precisebanktypes.ConversionFactor().QuoRaw(2), + precisebanktypes.ConversionFactor().QuoRaw(2), + }, + }, + { + "insufficient reserve", + sdk.NewCoin(precisebanktypes.IntegerCoinDenom, sdk.NewInt(1)), + []sdkmath.Int{ + // 4 accounts, total 2 int units + precisebanktypes.ConversionFactor().QuoRaw(2), + precisebanktypes.ConversionFactor().QuoRaw(2), + precisebanktypes.ConversionFactor().QuoRaw(2), + precisebanktypes.ConversionFactor().QuoRaw(2), + }, + }, + { + "extra reserve funds", + sdk.NewCoin(precisebanktypes.IntegerCoinDenom, sdk.NewInt(2)), + []sdkmath.Int{ + // 2 accounts, total 1 int units + precisebanktypes.ConversionFactor().QuoRaw(2), + precisebanktypes.ConversionFactor().QuoRaw(2), + }, + }, + { + "insufficient reserve, with remainder", + sdk.NewCoin(precisebanktypes.IntegerCoinDenom, sdk.NewInt(1)), + []sdkmath.Int{ + // 5 accounts, total 2.5 int units + // Expected 3 int units in reserve, 0.5 remainder + precisebanktypes.ConversionFactor().QuoRaw(2), + precisebanktypes.ConversionFactor().QuoRaw(2), + precisebanktypes.ConversionFactor().QuoRaw(2), + precisebanktypes.ConversionFactor().QuoRaw(2), + precisebanktypes.ConversionFactor().QuoRaw(2), + }, + }, + { + "extra reserve funds, with remainder", + sdk.NewCoin(precisebanktypes.IntegerCoinDenom, sdk.NewInt(3)), + []sdkmath.Int{ + // 3 accounts, total 1.5 int units. + // Expected 2 int units in reserve, 0.5 remainder + precisebanktypes.ConversionFactor().QuoRaw(2), + precisebanktypes.ConversionFactor().QuoRaw(2), + precisebanktypes.ConversionFactor().QuoRaw(2), + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tApp := app.NewTestApp() + tApp.InitializeFromGenesisStates() + ctx := tApp.NewContext(true, tmproto.Header{Height: 1, Time: time.Now()}) + + bk := tApp.GetBankKeeper() + pbk := tApp.GetPrecisebankKeeper() + err := bk.MintCoins(ctx, evmutiltypes.ModuleName, sdk.NewCoins(tt.initialReserve)) + require.NoError(t, err) + + oldReserveAddr := tApp.GetAccountKeeper().GetModuleAddress(evmutiltypes.ModuleName) + newReserveAddr := tApp.GetAccountKeeper().GetModuleAddress(precisebanktypes.ModuleName) + + // Double check balances + oldReserveBalance := bk.GetBalance(ctx, oldReserveAddr, precisebanktypes.IntegerCoinDenom) + newReserveBalance := bk.GetBalance(ctx, newReserveAddr, precisebanktypes.IntegerCoinDenom) + + require.Equal(t, tt.initialReserve, oldReserveBalance) + require.True(t, newReserveBalance.IsZero(), "empty initial new reserve") + + for i, balance := range tt.fractionalBalances { + addr := sdk.AccAddress([]byte{byte(i)}) + + require.NotPanics(t, func() { + pbk.SetFractionalBalance(ctx, addr, balance) + }, "given fractional balances should be valid") + } + + // Run reserve migration + err = app.TransferFractionalBalanceReserve( + ctx, + tApp.GetAccountKeeper(), + bk, + tApp.GetPrecisebankKeeper(), + ) + require.NoError(t, err) + + // Check old reserve is empty + oldReserveBalanceAfter := bk.GetBalance(ctx, oldReserveAddr, precisebanktypes.IntegerCoinDenom) + require.True(t, oldReserveBalanceAfter.IsZero(), "old reserve should be empty") + + // Check new reserve fully backs fractional balances + newReserveBalanceAfter := bk.GetBalance(ctx, newReserveAddr, precisebanktypes.IntegerCoinDenom) + fractionalBalanceTotal := pbk.GetTotalSumFractionalBalances(ctx) + + expectedReserveBal := fractionalBalanceTotal. + Quo(precisebanktypes.ConversionFactor()) + + // Check if theres a remainder + if fractionalBalanceTotal.Mod(precisebanktypes.ConversionFactor()).IsPositive() { + expectedReserveBal = expectedReserveBal.Add(sdkmath.OneInt()) + } + + require.Equal( + t, + expectedReserveBal, + newReserveBalanceAfter.Amount, + "new reserve should equal total fractional balances + remainder", + ) + }) + } +} diff --git a/build/lint.mk b/build/lint.mk new file mode 100644 index 00000000..905ee22d --- /dev/null +++ b/build/lint.mk @@ -0,0 +1,45 @@ +################################################################################ +### Required Variables ### +################################################################################ +ifndef DOCKER +$(error DOCKER not set) +endif + +ifndef BUILD_DIR +$(error BUILD_DIR not set) +endif + +################################################################################ +### Lint Settings ### +################################################################################ + +LINT_FROM_REV ?= $(shell git merge-base origin/master HEAD) + +GOLANGCI_VERSION ?= $(shell cat .golangci-version) +GOLANGCI_IMAGE_TAG ?= golangci/golangci-lint:$(GOLANGCI_VERSION) + +GOLANGCI_DIR ?= $(CURDIR)/$(BUILD_DIR)/.golangci-lint + +GOLANGCI_CACHE_DIR ?= $(GOLANGCI_DIR)/$(GOLANGCI_VERSION)-cache +GOLANGCI_MOD_CACHE_DIR ?= $(GOLANGCI_DIR)/go-mod + +################################################################################ +### Lint Target ### +################################################################################ + +.PHONY: lint +lint: $(GOLANGCI_CACHE_DIR) $(GOLANGCI_MOD_CACHE_DIR) + @echo "Running lint from rev $(LINT_FROM_REV), use LINT_FROM_REV var to override." + $(DOCKER) run -t --rm \ + -v $(GOLANGCI_CACHE_DIR):/root/.cache \ + -v $(GOLANGCI_MOD_CACHE_DIR):/go/pkg/mod \ + -v $(CURDIR):/app \ + -w /app \ + $(GOLANGCI_IMAGE_TAG) \ + golangci-lint run -v --new-from-rev $(LINT_FROM_REV) + +$(GOLANGCI_CACHE_DIR): + @mkdir -p $@ + +$(GOLANGCI_MOD_CACHE_DIR): + @mkdir -p $@ diff --git a/build/proto-deps.mk b/build/proto-deps.mk index 1a78f605..1856f59b 100644 --- a/build/proto-deps.mk +++ b/build/proto-deps.mk @@ -56,6 +56,7 @@ proto-update-deps: check-rsync ## Update all third party proto files @mkdir -p client/docs @cp -f $(COSMOS_SDK_PATH)/client/docs/swagger-ui/swagger.yaml client/docs/cosmos-swagger.yml @cp -f $(IBC_GO_PATH)/docs/client/swagger-ui/swagger.yaml client/docs/ibc-go-swagger.yml + @cp -f $(ETHERMINT_PATH)/client/docs/swagger-ui/swagger.yaml client/docs/ethermint-swagger.yml @mkdir -p $(COSMOS_PROTO_TYPES) @cp -f $(COSMOS_PROTO_PATH)/proto/cosmos_proto/cosmos.proto $(COSMOS_PROTO_TYPES)/cosmos.proto diff --git a/chaincfg/mint.go b/chaincfg/mint.go deleted file mode 100644 index 754dd86b..00000000 --- a/chaincfg/mint.go +++ /dev/null @@ -1,76 +0,0 @@ -package chaincfg - -import ( - "github.com/shopspring/decimal" - - sdk "github.com/cosmos/cosmos-sdk/types" - minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" -) - -var ( - Xmax, _ = sdk.NewDecFromStr("1.0") // upper limit on staked supply (as % of circ supply) - Ymin, _ = sdk.NewDecFromStr("0.05") // target APY at upper limit - - Xmin, _ = sdk.NewDecFromStr("0.2") // lower limit on staked supply (as % of circ supply) - Ymax, _ = sdk.NewDecFromStr("0.15") // target APY at lower limit - - decayRate, _ = sdk.NewDecFromStr("10") -) - -func decExp(x sdk.Dec) sdk.Dec { - xDec := decimal.NewFromBigInt(x.BigInt(), -18) - expDec, _ := xDec.ExpTaylor(18) - expInt := expDec.Shift(18).BigInt() - return sdk.NewDecFromBigIntWithPrec(expInt, 18) -} - -func NextInflationRate(ctx sdk.Context, minter minttypes.Minter, params minttypes.Params, bondedRatio sdk.Dec, circulatingRatio sdk.Dec) sdk.Dec { - X := bondedRatio.Quo(circulatingRatio) - - var apy sdk.Dec - if X.LT(Xmin) { - apy = Ymax - } else { - exp := decayRate.Neg().Mul(Xmax.Sub(Xmin)) - c := decExp(exp) - d := Ymin.Sub(Ymax.Mul(c)).Quo(sdk.OneDec().Sub(c)) - expBonded := decayRate.Neg().Mul(X.Sub(Xmin)) - cBonded := decExp(expBonded) - e := Ymax.Sub(d).Mul(cBonded) - apy = d.Add(e) - } - - inflation := apy.Mul(bondedRatio) - - // // The target annual inflation rate is recalculated for each previsions cycle. The - // // inflation is also subject to a rate change (positive or negative) depending on - // // the distance from the desired ratio (67%). The maximum rate change possible is - // // defined to be 13% per year, however the annual inflation is capped as between - // // 7% and 20%. - - // // (1 - bondedRatio/GoalBonded) * InflationRateChange - // inflationRateChangePerYear := sdk.OneDec(). - // Sub(bondedRatio.Quo(params.GoalBonded)). - // Mul(params.InflationRateChange) - // inflationRateChange := inflationRateChangePerYear.Quo(sdk.NewDec(int64(params.BlocksPerYear))) - - // // adjust the new annual inflation for this next cycle - // inflation := minter.Inflation.Add(inflationRateChange) // note inflationRateChange may be negative - // if inflation.GT(params.InflationMax) { - // inflation = params.InflationMax - // } - // if inflation.LT(params.InflationMin) { - // inflation = params.InflationMin - // } - - ctx.Logger().Info( - "nextInflationRate", - "bondedRatio", bondedRatio, - "circulatingRatio", circulatingRatio, - "apy", apy, - "inflation", inflation, - "params", params, - "minter", minter, - ) - return inflation -} diff --git a/ci/env/kava-internal-testnet/KAVA.VERSION b/ci/env/kava-internal-testnet/KAVA.VERSION index 68e9ea31..48a4cb7b 100644 --- a/ci/env/kava-internal-testnet/KAVA.VERSION +++ b/ci/env/kava-internal-testnet/KAVA.VERSION @@ -1 +1 @@ -a967d2fdda299ec8e1e3b99fb55bd06ecfdb0469 +6862cde560c70cb82f7908e6cef22ca223465bd2 diff --git a/ci/env/kava-internal-testnet/genesis.json b/ci/env/kava-internal-testnet/genesis.json index 4ffe47c7..75dbb12c 100644 --- a/ci/env/kava-internal-testnet/genesis.json +++ b/ci/env/kava-internal-testnet/genesis.json @@ -22,6 +22,8 @@ }, "app_hash": "", "app_state": { + "06-solomachine": null, + "07-tendermint": null, "auction": { "next_auction_id": "1", "params": { @@ -505,6 +507,10 @@ { "address": "kava1vlpsrmdyuywvaqrv7rx6xga224sqfwz3fyfhwq", "coins": [ + { + "denom": "bnb", + "amount": "500000000" + }, { "denom": "btcb", "amount": "200000000" @@ -525,6 +531,10 @@ "denom": "erc20/axelar/wbtc", "amount": "1000000000" }, + { + "denom": "erc20/bitgo/wbtc", + "amount": "200000000" + }, { "denom": "erc20/multichain/usdc", "amount": "1000000000000000000" @@ -556,12 +566,20 @@ { "denom": "usdx", "amount": "103000000000" + }, + { + "denom": "xrpb", + "amount": "1000000000000000" } ] }, { "address": "kava1krh7k30pc9rteejpl2zycj0vau58y8c69xkzws", "coins": [ + { + "denom": "bnb", + "amount": "100000000000000000" + }, { "denom": "btcb", "amount": "200000000" @@ -582,6 +600,10 @@ "denom": "erc20/axelar/wbtc", "amount": "1000000000" }, + { + "denom": "erc20/bitgo/wbtc", + "amount": "200000000" + }, { "denom": "erc20/tether/usdt", "amount": "100000000000" @@ -601,6 +623,10 @@ { "denom": "usdx", "amount": "103000000000" + }, + { + "denom": "xrpb", + "amount": "103000000000" } ] }, @@ -822,6 +848,7 @@ "gov_denom": "ukava", "params": { "circuit_breaker": false, + "liquidation_block_interval": 500, "collateral_params": [ { "denom": "bnb", @@ -993,8 +1020,7 @@ "check_collateralization_index_count": "10", "conversion_factor": "6" } - ] - , + ], "debt_auction_lot": "10000000000", "debt_auction_threshold": "100000000000", "debt_param": { @@ -1241,7 +1267,15 @@ "votes": [] }, "community": { - "params": {} + "params": { + "upgrade_time_disable_inflation": "2023-11-01T00:00:00Z", + "upgrade_time_set_staking_rewards_per_second": "744191", + "staking_rewards_per_second": "0" + }, + "staking_rewards_state": { + "last_accumulation_time": "0001-01-01T00:00:00Z", + "last_truncation_error": "0" + } }, "crisis": { "constant_fee": { @@ -2067,6 +2101,25 @@ } ], "nested_types": [] + }, + { + "msg_type_url": "/kava.committee.v1beta1.MsgVote", + "msg_value_type_name": "MsgValueCommitteeVote", + "value_types": [ + { + "name": "proposal_id", + "type": "uint64" + }, + { + "name": "voter", + "type": "string" + }, + { + "name": "vote_type", + "type": "int32" + } + ], + "nested_types": [] } ], "allow_unprotected_txs": false @@ -2229,22 +2282,27 @@ "deposits": [], "votes": [], "proposals": [], - "deposit_params": { + "deposit_params": null, + "voting_params": { + "voting_period": "604800s" + }, + "tally_params": null, + "params": { "min_deposit": [ { "denom": "ukava", "amount": "10000000" } ], - "max_deposit_period": "172800s" - }, - "voting_params": { - "voting_period": "600s" - }, - "tally_params": { + "max_deposit_period": "172800s", + "voting_period": "604800s", "quorum": "0.334000000000000000", "threshold": "0.500000000000000000", - "veto_threshold": "0.334000000000000000" + "veto_threshold": "0.334000000000000000", + "min_initial_deposit_ratio": "0.000000000000000000", + "burn_vote_quorum": false, + "burn_proposal_deposit_prevote": false, + "burn_vote_veto": true } }, "hard": { @@ -2519,6 +2577,24 @@ }, "reserve_factor": "0.025000000000000000", "keeper_reward_percentage": "0.020000000000000000" + }, + { + "denom": "erc20/bitgo/wbtc", + "borrow_limit": { + "has_max_limit": true, + "maximum_limit": "0.000000000000000000", + "loan_to_value": "0.000000000000000000" + }, + "spot_market_id": "btc:usd:30", + "conversion_factor": "100000000", + "interest_rate_model": { + "base_rate_apy": "0.000000000000000000", + "base_multiplier": "0.050000000000000000", + "kink": "0.800000000000000000", + "jump_multiplier": "5.000000000000000000" + }, + "reserve_factor": "0.025000000000000000", + "keeper_reward_percentage": "0.020000000000000000" } ], "minimum_borrow_usd_value": "10.000000000000000000" @@ -2734,6 +2810,18 @@ "amount": "787" } ] + }, + { + "active": true, + "collateral_type": "erc20/bitgo/wbtc", + "start": "2022-11-11T15:00:00Z", + "end": "2025-11-11T15:00:00Z", + "rewards_per_second": [ + { + "denom": "ukava", + "amount": "787" + } + ] } ], "hard_borrow_reward_periods": [], @@ -3170,6 +3258,16 @@ } }, "params": null, + "packetfowardmiddleware": { + "params": { + "fee_percentage": "0.000000000000000000" + }, + "in_flight_packets": {} + }, + "precisebank": { + "balances": [], + "remainder": "0" + }, "pricefeed": { "params": { "markets": [ @@ -3643,6 +3741,7 @@ } ] }, + "router": {}, "savings": { "params": { "supported_denoms": [ @@ -3814,7 +3913,8 @@ "params": { "send_enabled": true, "receive_enabled": true - } + }, + "total_escrowed": [] }, "upgrade": {}, "validatorvesting": null, diff --git a/ci/env/kava-protonet/genesis.json b/ci/env/kava-protonet/genesis.json index f252771c..e42273ea 100644 --- a/ci/env/kava-protonet/genesis.json +++ b/ci/env/kava-protonet/genesis.json @@ -3006,6 +3006,9 @@ }, "in_flight_packets": {} }, + "precisebank": { + "remainder": "0" + }, "pricefeed": { "params": { "markets": [ diff --git a/client/docs/config.json b/client/docs/config.json index 0fd99b33..35406950 100644 --- a/client/docs/config.json +++ b/client/docs/config.json @@ -182,6 +182,23 @@ ] } }, + { + "url": "./out/swagger/kava/precisebank/v1/query.swagger.json", + "tags": { + "rename": { + "Query": "Precisebank" + } + }, + "operationIds": { + "rename": [ + { + "type": "regex", + "from": "(.*)", + "to": "Precisebank$1" + } + ] + } + }, { "url": "./out/swagger/kava/pricefeed/v1beta1/query.swagger.json", "tags": { @@ -295,6 +312,30 @@ ] } }, + { + "url": "./client/docs/ethermint-swagger.yml", + "dereference": { + "circular": "ignore" + }, + "tags": { + "rename": { + "Query": "Ethermint" + } + }, + "operationIds": { + "rename": [ + { + "type": "regex", + "from": "(.*)", + "to": "Ethermint$1" + } + ] + }, + "paths": { + "exclude": [ + ] + } + }, { "url": "./client/docs/legacy-swagger.yml", "dereference": { diff --git a/client/docs/ethermint-swagger.yml b/client/docs/ethermint-swagger.yml new file mode 100644 index 00000000..e8ff3a4a --- /dev/null +++ b/client/docs/ethermint-swagger.yml @@ -0,0 +1,4458 @@ +swagger: '2.0' +info: + title: Ethermint Chain - Legacy REST and gRPC Gateway docs + description: A REST interface for state queries, legacy transactions + version: 1.0.0 +paths: + /ethermint/evm/v1/account/{address}: + get: + summary: Account queries an Ethereum account. + operationId: Account + responses: + '200': + description: A successful response. + schema: + type: object + properties: + balance: + type: string + description: balance is the balance of the EVM denomination. + code_hash: + type: string + description: code hash is the hex-formatted code bytes from the EOA. + nonce: + type: string + format: uint64 + description: nonce is the account's sequence number. + description: >- + QueryAccountResponse is the response type for the Query/Account + RPC method. + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of + the serialized + + protocol buffer message. This string must contain at + least + + one "/" character. The last segment of the URL's path + must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in + a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary + all types that they + + expect it to use in the context of Any. However, for + URLs which use the + + scheme `http`, `https`, or no scheme, one can optionally + set up a type + + server that maps type URLs to message definitions as + follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based + on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in + the official + + protobuf release, and it is not used for type URLs + beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) + might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer + message along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values + in the form + + of utility functions or additional generated methods of the + Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := anypb.New(foo) + if err != nil { + ... + } + ... + foo := &pb.Foo{} + if err := any.UnmarshalTo(foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by + default use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the + last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield + type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with + an + + additional field `@type` which contains the type URL. + Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom + JSON + + representation, that representation will be embedded adding + a field + + `value` which holds the custom JSON in addition to the + `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + parameters: + - name: address + description: address is the ethereum hex address to query the account for. + in: path + required: true + type: string + tags: + - Query + /ethermint/evm/v1/balances/{address}: + get: + summary: |- + Balance queries the balance of a the EVM denomination for a single + EthAccount. + operationId: Balance + responses: + '200': + description: A successful response. + schema: + type: object + properties: + balance: + type: string + description: balance is the balance of the EVM denomination. + description: >- + QueryBalanceResponse is the response type for the Query/Balance + RPC method. + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of + the serialized + + protocol buffer message. This string must contain at + least + + one "/" character. The last segment of the URL's path + must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in + a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary + all types that they + + expect it to use in the context of Any. However, for + URLs which use the + + scheme `http`, `https`, or no scheme, one can optionally + set up a type + + server that maps type URLs to message definitions as + follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based + on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in + the official + + protobuf release, and it is not used for type URLs + beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) + might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer + message along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values + in the form + + of utility functions or additional generated methods of the + Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := anypb.New(foo) + if err != nil { + ... + } + ... + foo := &pb.Foo{} + if err := any.UnmarshalTo(foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by + default use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the + last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield + type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with + an + + additional field `@type` which contains the type URL. + Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom + JSON + + representation, that representation will be embedded adding + a field + + `value` which holds the custom JSON in addition to the + `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + parameters: + - name: address + description: address is the ethereum hex address to query the balance for. + in: path + required: true + type: string + tags: + - Query + /ethermint/evm/v1/base_fee: + get: + summary: >- + BaseFee queries the base fee of the parent block of the current block, + + it's similar to feemarket module's method, but also checks london + hardfork status. + operationId: BaseFee + responses: + '200': + description: A successful response. + schema: + type: object + properties: + base_fee: + type: string + description: BaseFeeResponse returns the EIP1559 base fee. + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of + the serialized + + protocol buffer message. This string must contain at + least + + one "/" character. The last segment of the URL's path + must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in + a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary + all types that they + + expect it to use in the context of Any. However, for + URLs which use the + + scheme `http`, `https`, or no scheme, one can optionally + set up a type + + server that maps type URLs to message definitions as + follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based + on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in + the official + + protobuf release, and it is not used for type URLs + beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) + might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer + message along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values + in the form + + of utility functions or additional generated methods of the + Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := anypb.New(foo) + if err != nil { + ... + } + ... + foo := &pb.Foo{} + if err := any.UnmarshalTo(foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by + default use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the + last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield + type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with + an + + additional field `@type` which contains the type URL. + Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom + JSON + + representation, that representation will be embedded adding + a field + + `value` which holds the custom JSON in addition to the + `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + tags: + - Query + /ethermint/evm/v1/codes/{address}: + get: + summary: Code queries the balance of all coins for a single account. + operationId: Code + responses: + '200': + description: A successful response. + schema: + type: object + properties: + code: + type: string + format: byte + description: code represents the code bytes from an ethereum address. + description: |- + QueryCodeResponse is the response type for the Query/Code RPC + method. + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of + the serialized + + protocol buffer message. This string must contain at + least + + one "/" character. The last segment of the URL's path + must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in + a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary + all types that they + + expect it to use in the context of Any. However, for + URLs which use the + + scheme `http`, `https`, or no scheme, one can optionally + set up a type + + server that maps type URLs to message definitions as + follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based + on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in + the official + + protobuf release, and it is not used for type URLs + beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) + might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer + message along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values + in the form + + of utility functions or additional generated methods of the + Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := anypb.New(foo) + if err != nil { + ... + } + ... + foo := &pb.Foo{} + if err := any.UnmarshalTo(foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by + default use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the + last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield + type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with + an + + additional field `@type` which contains the type URL. + Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom + JSON + + representation, that representation will be embedded adding + a field + + `value` which holds the custom JSON in addition to the + `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + parameters: + - name: address + description: address is the ethereum hex address to query the code for. + in: path + required: true + type: string + tags: + - Query + /ethermint/evm/v1/cosmos_account/{address}: + get: + summary: CosmosAccount queries an Ethereum account's Cosmos Address. + operationId: CosmosAccount + responses: + '200': + description: A successful response. + schema: + type: object + properties: + cosmos_address: + type: string + description: cosmos_address is the cosmos address of the account. + sequence: + type: string + format: uint64 + description: sequence is the account's sequence number. + account_number: + type: string + format: uint64 + title: account_number is the account numbert + description: >- + QueryCosmosAccountResponse is the response type for the + Query/CosmosAccount + + RPC method. + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of + the serialized + + protocol buffer message. This string must contain at + least + + one "/" character. The last segment of the URL's path + must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in + a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary + all types that they + + expect it to use in the context of Any. However, for + URLs which use the + + scheme `http`, `https`, or no scheme, one can optionally + set up a type + + server that maps type URLs to message definitions as + follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based + on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in + the official + + protobuf release, and it is not used for type URLs + beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) + might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer + message along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values + in the form + + of utility functions or additional generated methods of the + Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := anypb.New(foo) + if err != nil { + ... + } + ... + foo := &pb.Foo{} + if err := any.UnmarshalTo(foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by + default use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the + last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield + type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with + an + + additional field `@type` which contains the type URL. + Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom + JSON + + representation, that representation will be embedded adding + a field + + `value` which holds the custom JSON in addition to the + `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + parameters: + - name: address + description: address is the ethereum hex address to query the account for. + in: path + required: true + type: string + tags: + - Query + /ethermint/evm/v1/estimate_gas: + get: + summary: EstimateGas implements the `eth_estimateGas` rpc api + operationId: EstimateGas + responses: + '200': + description: A successful response. + schema: + type: object + properties: + gas: + type: string + format: uint64 + title: the estimated gas + title: EstimateGasResponse defines EstimateGas response + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of + the serialized + + protocol buffer message. This string must contain at + least + + one "/" character. The last segment of the URL's path + must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in + a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary + all types that they + + expect it to use in the context of Any. However, for + URLs which use the + + scheme `http`, `https`, or no scheme, one can optionally + set up a type + + server that maps type URLs to message definitions as + follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based + on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in + the official + + protobuf release, and it is not used for type URLs + beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) + might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer + message along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values + in the form + + of utility functions or additional generated methods of the + Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := anypb.New(foo) + if err != nil { + ... + } + ... + foo := &pb.Foo{} + if err := any.UnmarshalTo(foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by + default use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the + last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield + type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with + an + + additional field `@type` which contains the type URL. + Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom + JSON + + representation, that representation will be embedded adding + a field + + `value` which holds the custom JSON in addition to the + `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + parameters: + - name: args + description: same json format as the json rpc api. + in: query + required: false + type: string + format: byte + - name: gas_cap + description: the default gas cap to be used. + in: query + required: false + type: string + format: uint64 + - name: proposer_address + description: the proposer of the requested block. + in: query + required: false + type: string + format: byte + - name: chain_id + description: the eip155 chain id parsed from the requested block header. + in: query + required: false + type: string + format: int64 + tags: + - Query + /ethermint/evm/v1/eth_call: + get: + summary: EthCall implements the `eth_call` rpc api + operationId: EthCall + responses: + '200': + description: A successful response. + schema: + type: object + properties: + hash: + type: string + title: >- + ethereum transaction hash in hex format. This hash differs + from the + + Tendermint sha256 hash of the transaction bytes. See + + https://github.com/tendermint/tendermint/issues/6539 for + reference + logs: + type: array + items: + type: object + properties: + address: + type: string + title: address of the contract that generated the event + topics: + type: array + items: + type: string + description: list of topics provided by the contract. + data: + type: string + format: byte + title: supplied by the contract, usually ABI-encoded + block_number: + type: string + format: uint64 + title: block in which the transaction was included + tx_hash: + type: string + title: hash of the transaction + tx_index: + type: string + format: uint64 + title: index of the transaction in the block + block_hash: + type: string + title: hash of the block in which the transaction was included + index: + type: string + format: uint64 + title: index of the log in the block + removed: + type: boolean + description: >- + The Removed field is true if this log was reverted due + to a chain + + reorganisation. You must pay attention to this field if + you receive logs + + through a filter query. + description: >- + Log represents an protobuf compatible Ethereum Log that + defines a contract + + log event. These events are generated by the LOG opcode and + stored/indexed by + + the node. + description: >- + logs contains the transaction hash and the proto-compatible + ethereum + + logs. + ret: + type: string + format: byte + title: >- + returned data from evm function (result or data supplied with + revert + + opcode) + vm_error: + type: string + title: vm error is the error returned by vm execution + gas_used: + type: string + format: uint64 + title: gas consumed by the transaction + description: MsgEthereumTxResponse defines the Msg/EthereumTx response type. + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of + the serialized + + protocol buffer message. This string must contain at + least + + one "/" character. The last segment of the URL's path + must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in + a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary + all types that they + + expect it to use in the context of Any. However, for + URLs which use the + + scheme `http`, `https`, or no scheme, one can optionally + set up a type + + server that maps type URLs to message definitions as + follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based + on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in + the official + + protobuf release, and it is not used for type URLs + beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) + might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer + message along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values + in the form + + of utility functions or additional generated methods of the + Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := anypb.New(foo) + if err != nil { + ... + } + ... + foo := &pb.Foo{} + if err := any.UnmarshalTo(foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by + default use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the + last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield + type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with + an + + additional field `@type` which contains the type URL. + Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom + JSON + + representation, that representation will be embedded adding + a field + + `value` which holds the custom JSON in addition to the + `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + parameters: + - name: args + description: same json format as the json rpc api. + in: query + required: false + type: string + format: byte + - name: gas_cap + description: the default gas cap to be used. + in: query + required: false + type: string + format: uint64 + - name: proposer_address + description: the proposer of the requested block. + in: query + required: false + type: string + format: byte + - name: chain_id + description: the eip155 chain id parsed from the requested block header. + in: query + required: false + type: string + format: int64 + tags: + - Query + /ethermint/evm/v1/params: + get: + summary: Params queries the parameters of x/evm module. + operationId: EvmParams + responses: + '200': + description: A successful response. + schema: + type: object + properties: + params: + description: params define the evm module parameters. + type: object + properties: + evm_denom: + type: string + description: >- + evm denom represents the token denomination used to run + the EVM state + + transitions. + enable_create: + type: boolean + title: >- + enable create toggles state transitions that use the + vm.Create function + enable_call: + type: boolean + title: >- + enable call toggles state transitions that use the vm.Call + function + extra_eips: + type: array + items: + type: string + format: int64 + title: extra eips defines the additional EIPs for the vm.Config + chain_config: + title: >- + chain config defines the EVM chain configuration + parameters + type: object + properties: + homestead_block: + type: string + title: >- + Homestead switch block (nil no fork, 0 = already + homestead) + dao_fork_block: + type: string + title: TheDAO hard-fork switch block (nil no fork) + dao_fork_support: + type: boolean + title: >- + Whether the nodes supports or opposes the DAO + hard-fork + eip150_block: + type: string + title: >- + EIP150 implements the Gas price changes + + (https://github.com/ethereum/EIPs/issues/150) EIP150 + HF block (nil no fork) + eip150_hash: + type: string + title: >- + EIP150 HF hash (needed for header only clients as only + gas pricing changed) + eip155_block: + type: string + title: EIP155Block HF block + eip158_block: + type: string + title: EIP158 HF block + byzantium_block: + type: string + title: >- + Byzantium switch block (nil no fork, 0 = already on + byzantium) + constantinople_block: + type: string + title: >- + Constantinople switch block (nil no fork, 0 = already + activated) + petersburg_block: + type: string + title: Petersburg switch block (nil same as Constantinople) + istanbul_block: + type: string + title: >- + Istanbul switch block (nil no fork, 0 = already on + istanbul) + muir_glacier_block: + type: string + title: >- + Eip-2384 (bomb delay) switch block (nil no fork, 0 = + already activated) + berlin_block: + type: string + title: >- + Berlin switch block (nil = no fork, 0 = already on + berlin) + london_block: + type: string + title: >- + London switch block (nil = no fork, 0 = already on + london) + arrow_glacier_block: + type: string + title: >- + Eip-4345 (bomb delay) switch block (nil = no fork, 0 = + already activated) + gray_glacier_block: + type: string + title: >- + EIP-5133 (bomb delay) switch block (nil = no fork, 0 = + already activated) + merge_netsplit_block: + type: string + title: >- + Virtual fork after The Merge to use as a network + splitter + description: >- + ChainConfig defines the Ethereum ChainConfig parameters + using *sdk.Int values + + instead of *big.Int. + allow_unprotected_txs: + type: boolean + description: >- + Allow unprotected transactions defines if replay-protected + (i.e non EIP155 + + signed) transactions can be executed on the state machine. + title: Params defines the EVM module parameters + description: >- + QueryParamsResponse defines the response type for querying x/evm + parameters. + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of + the serialized + + protocol buffer message. This string must contain at + least + + one "/" character. The last segment of the URL's path + must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in + a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary + all types that they + + expect it to use in the context of Any. However, for + URLs which use the + + scheme `http`, `https`, or no scheme, one can optionally + set up a type + + server that maps type URLs to message definitions as + follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based + on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in + the official + + protobuf release, and it is not used for type URLs + beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) + might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer + message along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values + in the form + + of utility functions or additional generated methods of the + Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := anypb.New(foo) + if err != nil { + ... + } + ... + foo := &pb.Foo{} + if err := any.UnmarshalTo(foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by + default use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the + last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield + type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with + an + + additional field `@type` which contains the type URL. + Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom + JSON + + representation, that representation will be embedded adding + a field + + `value` which holds the custom JSON in addition to the + `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + tags: + - Query + /ethermint/evm/v1/storage/{address}/{key}: + get: + summary: Storage queries the balance of all coins for a single account. + operationId: Storage + responses: + '200': + description: A successful response. + schema: + type: object + properties: + value: + type: string + description: >- + key defines the storage state value hash associated with the + given key. + description: >- + QueryStorageResponse is the response type for the Query/Storage + RPC + + method. + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of + the serialized + + protocol buffer message. This string must contain at + least + + one "/" character. The last segment of the URL's path + must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in + a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary + all types that they + + expect it to use in the context of Any. However, for + URLs which use the + + scheme `http`, `https`, or no scheme, one can optionally + set up a type + + server that maps type URLs to message definitions as + follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based + on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in + the official + + protobuf release, and it is not used for type URLs + beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) + might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer + message along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values + in the form + + of utility functions or additional generated methods of the + Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := anypb.New(foo) + if err != nil { + ... + } + ... + foo := &pb.Foo{} + if err := any.UnmarshalTo(foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by + default use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the + last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield + type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with + an + + additional field `@type` which contains the type URL. + Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom + JSON + + representation, that representation will be embedded adding + a field + + `value` which holds the custom JSON in addition to the + `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + parameters: + - name: address + description: >- + / address is the ethereum hex address to query the storage state + for. + in: path + required: true + type: string + - name: key + description: key defines the key of the storage state + in: path + required: true + type: string + tags: + - Query + /ethermint/evm/v1/trace_block: + get: + summary: >- + TraceBlock implements the `debug_traceBlockByNumber` and + `debug_traceBlockByHash` rpc api + operationId: TraceBlock + responses: + '200': + description: A successful response. + schema: + type: object + properties: + data: + type: string + format: byte + title: QueryTraceBlockResponse defines TraceBlock response + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of + the serialized + + protocol buffer message. This string must contain at + least + + one "/" character. The last segment of the URL's path + must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in + a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary + all types that they + + expect it to use in the context of Any. However, for + URLs which use the + + scheme `http`, `https`, or no scheme, one can optionally + set up a type + + server that maps type URLs to message definitions as + follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based + on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in + the official + + protobuf release, and it is not used for type URLs + beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) + might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer + message along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values + in the form + + of utility functions or additional generated methods of the + Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := anypb.New(foo) + if err != nil { + ... + } + ... + foo := &pb.Foo{} + if err := any.UnmarshalTo(foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by + default use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the + last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield + type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with + an + + additional field `@type` which contains the type URL. + Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom + JSON + + representation, that representation will be embedded adding + a field + + `value` which holds the custom JSON in addition to the + `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + parameters: + - name: trace_config.tracer + description: custom javascript tracer. + in: query + required: false + type: string + - name: trace_config.timeout + description: >- + overrides the default timeout of 5 seconds for JavaScript-based + tracing + + calls. + in: query + required: false + type: string + - name: trace_config.reexec + description: number of blocks the tracer is willing to go back. + in: query + required: false + type: string + format: uint64 + - name: trace_config.disable_stack + description: disable stack capture. + in: query + required: false + type: boolean + - name: trace_config.disable_storage + description: disable storage capture. + in: query + required: false + type: boolean + - name: trace_config.debug + description: print output during capture end. + in: query + required: false + type: boolean + - name: trace_config.limit + description: maximum length of output, but zero means unlimited. + in: query + required: false + type: integer + format: int32 + - name: trace_config.overrides.homestead_block + description: Homestead switch block (nil no fork, 0 = already homestead). + in: query + required: false + type: string + - name: trace_config.overrides.dao_fork_block + description: TheDAO hard-fork switch block (nil no fork). + in: query + required: false + type: string + - name: trace_config.overrides.dao_fork_support + description: Whether the nodes supports or opposes the DAO hard-fork. + in: query + required: false + type: boolean + - name: trace_config.overrides.eip150_block + description: >- + EIP150 implements the Gas price changes + + (https://github.com/ethereum/EIPs/issues/150) EIP150 HF block (nil + no fork). + in: query + required: false + type: string + - name: trace_config.overrides.eip150_hash + description: >- + EIP150 HF hash (needed for header only clients as only gas pricing + changed). + in: query + required: false + type: string + - name: trace_config.overrides.eip155_block + description: EIP155Block HF block. + in: query + required: false + type: string + - name: trace_config.overrides.eip158_block + description: EIP158 HF block. + in: query + required: false + type: string + - name: trace_config.overrides.byzantium_block + description: Byzantium switch block (nil no fork, 0 = already on byzantium). + in: query + required: false + type: string + - name: trace_config.overrides.constantinople_block + description: Constantinople switch block (nil no fork, 0 = already activated). + in: query + required: false + type: string + - name: trace_config.overrides.petersburg_block + description: Petersburg switch block (nil same as Constantinople). + in: query + required: false + type: string + - name: trace_config.overrides.istanbul_block + description: Istanbul switch block (nil no fork, 0 = already on istanbul). + in: query + required: false + type: string + - name: trace_config.overrides.muir_glacier_block + description: >- + Eip-2384 (bomb delay) switch block (nil no fork, 0 = already + activated). + in: query + required: false + type: string + - name: trace_config.overrides.berlin_block + description: Berlin switch block (nil = no fork, 0 = already on berlin). + in: query + required: false + type: string + - name: trace_config.overrides.london_block + description: London switch block (nil = no fork, 0 = already on london). + in: query + required: false + type: string + - name: trace_config.overrides.arrow_glacier_block + description: >- + Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already + activated). + in: query + required: false + type: string + - name: trace_config.overrides.gray_glacier_block + description: >- + EIP-5133 (bomb delay) switch block (nil = no fork, 0 = already + activated). + in: query + required: false + type: string + - name: trace_config.overrides.merge_netsplit_block + description: Virtual fork after The Merge to use as a network splitter. + in: query + required: false + type: string + - name: trace_config.enable_memory + description: enable memory capture. + in: query + required: false + type: boolean + - name: trace_config.enable_return_data + description: enable return data capture. + in: query + required: false + type: boolean + - name: trace_config.tracer_json_config + description: tracer config. + in: query + required: false + type: string + - name: block_number + description: block number. + in: query + required: false + type: string + format: int64 + - name: block_hash + description: block hex hash. + in: query + required: false + type: string + - name: block_time + description: block time. + in: query + required: false + type: string + format: date-time + - name: proposer_address + description: the proposer of the requested block. + in: query + required: false + type: string + format: byte + - name: chain_id + description: the eip155 chain id parsed from the requested block header. + in: query + required: false + type: string + format: int64 + tags: + - Query + /ethermint/evm/v1/trace_tx: + get: + summary: TraceTx implements the `debug_traceTransaction` rpc api + operationId: TraceTx + responses: + '200': + description: A successful response. + schema: + type: object + properties: + data: + type: string + format: byte + title: response serialized in bytes + title: QueryTraceTxResponse defines TraceTx response + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of + the serialized + + protocol buffer message. This string must contain at + least + + one "/" character. The last segment of the URL's path + must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in + a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary + all types that they + + expect it to use in the context of Any. However, for + URLs which use the + + scheme `http`, `https`, or no scheme, one can optionally + set up a type + + server that maps type URLs to message definitions as + follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based + on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in + the official + + protobuf release, and it is not used for type URLs + beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) + might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer + message along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values + in the form + + of utility functions or additional generated methods of the + Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := anypb.New(foo) + if err != nil { + ... + } + ... + foo := &pb.Foo{} + if err := any.UnmarshalTo(foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by + default use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the + last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield + type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with + an + + additional field `@type` which contains the type URL. + Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom + JSON + + representation, that representation will be embedded adding + a field + + `value` which holds the custom JSON in addition to the + `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + parameters: + - name: msg.data.type_url + description: >- + A URL/resource name that uniquely identifies the type of the + serialized + + protocol buffer message. This string must contain at least + + one "/" character. The last segment of the URL's path must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in a canonical + form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary all types that + they + + expect it to use in the context of Any. However, for URLs which use + the + + scheme `http`, `https`, or no scheme, one can optionally set up a + type + + server that maps type URLs to message definitions as follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in the official + + protobuf release, and it is not used for type URLs beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) might be + + used with implementation specific semantics. + in: query + required: false + type: string + - name: msg.data.value + description: >- + Must be a valid serialized protocol buffer of the above specified + type. + in: query + required: false + type: string + format: byte + - name: msg.size + description: 'DEPRECATED: encoded storage size of the transaction.' + in: query + required: false + type: number + format: double + - name: msg.hash + description: transaction hash in hex format. + in: query + required: false + type: string + - name: msg.from + description: |- + ethereum signer address in hex format. This address value is checked + against the address derived from the signature (V, R, S) using the + secp256k1 elliptic curve. + in: query + required: false + type: string + - name: trace_config.tracer + description: custom javascript tracer. + in: query + required: false + type: string + - name: trace_config.timeout + description: >- + overrides the default timeout of 5 seconds for JavaScript-based + tracing + + calls. + in: query + required: false + type: string + - name: trace_config.reexec + description: number of blocks the tracer is willing to go back. + in: query + required: false + type: string + format: uint64 + - name: trace_config.disable_stack + description: disable stack capture. + in: query + required: false + type: boolean + - name: trace_config.disable_storage + description: disable storage capture. + in: query + required: false + type: boolean + - name: trace_config.debug + description: print output during capture end. + in: query + required: false + type: boolean + - name: trace_config.limit + description: maximum length of output, but zero means unlimited. + in: query + required: false + type: integer + format: int32 + - name: trace_config.overrides.homestead_block + description: Homestead switch block (nil no fork, 0 = already homestead). + in: query + required: false + type: string + - name: trace_config.overrides.dao_fork_block + description: TheDAO hard-fork switch block (nil no fork). + in: query + required: false + type: string + - name: trace_config.overrides.dao_fork_support + description: Whether the nodes supports or opposes the DAO hard-fork. + in: query + required: false + type: boolean + - name: trace_config.overrides.eip150_block + description: >- + EIP150 implements the Gas price changes + + (https://github.com/ethereum/EIPs/issues/150) EIP150 HF block (nil + no fork). + in: query + required: false + type: string + - name: trace_config.overrides.eip150_hash + description: >- + EIP150 HF hash (needed for header only clients as only gas pricing + changed). + in: query + required: false + type: string + - name: trace_config.overrides.eip155_block + description: EIP155Block HF block. + in: query + required: false + type: string + - name: trace_config.overrides.eip158_block + description: EIP158 HF block. + in: query + required: false + type: string + - name: trace_config.overrides.byzantium_block + description: Byzantium switch block (nil no fork, 0 = already on byzantium). + in: query + required: false + type: string + - name: trace_config.overrides.constantinople_block + description: Constantinople switch block (nil no fork, 0 = already activated). + in: query + required: false + type: string + - name: trace_config.overrides.petersburg_block + description: Petersburg switch block (nil same as Constantinople). + in: query + required: false + type: string + - name: trace_config.overrides.istanbul_block + description: Istanbul switch block (nil no fork, 0 = already on istanbul). + in: query + required: false + type: string + - name: trace_config.overrides.muir_glacier_block + description: >- + Eip-2384 (bomb delay) switch block (nil no fork, 0 = already + activated). + in: query + required: false + type: string + - name: trace_config.overrides.berlin_block + description: Berlin switch block (nil = no fork, 0 = already on berlin). + in: query + required: false + type: string + - name: trace_config.overrides.london_block + description: London switch block (nil = no fork, 0 = already on london). + in: query + required: false + type: string + - name: trace_config.overrides.arrow_glacier_block + description: >- + Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already + activated). + in: query + required: false + type: string + - name: trace_config.overrides.gray_glacier_block + description: >- + EIP-5133 (bomb delay) switch block (nil = no fork, 0 = already + activated). + in: query + required: false + type: string + - name: trace_config.overrides.merge_netsplit_block + description: Virtual fork after The Merge to use as a network splitter. + in: query + required: false + type: string + - name: trace_config.enable_memory + description: enable memory capture. + in: query + required: false + type: boolean + - name: trace_config.enable_return_data + description: enable return data capture. + in: query + required: false + type: boolean + - name: trace_config.tracer_json_config + description: tracer config. + in: query + required: false + type: string + - name: block_number + description: block number of requested transaction. + in: query + required: false + type: string + format: int64 + - name: block_hash + description: block hex hash of requested transaction. + in: query + required: false + type: string + - name: block_time + description: block time of requested transaction. + in: query + required: false + type: string + format: date-time + - name: proposer_address + description: the proposer of the requested block. + in: query + required: false + type: string + format: byte + - name: chain_id + description: the eip155 chain id parsed from the requested block header. + in: query + required: false + type: string + format: int64 + tags: + - Query + /ethermint/evm/v1/validator_account/{cons_address}: + get: + summary: >- + ValidatorAccount queries an Ethereum account's from a validator + consensus + + Address. + operationId: ValidatorAccount + responses: + '200': + description: A successful response. + schema: + type: object + properties: + account_address: + type: string + description: >- + account_address is the cosmos address of the account in bech32 + format. + sequence: + type: string + format: uint64 + description: sequence is the account's sequence number. + account_number: + type: string + format: uint64 + title: account_number is the account number + description: |- + QueryValidatorAccountResponse is the response type for the + Query/ValidatorAccount RPC method. + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of + the serialized + + protocol buffer message. This string must contain at + least + + one "/" character. The last segment of the URL's path + must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in + a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary + all types that they + + expect it to use in the context of Any. However, for + URLs which use the + + scheme `http`, `https`, or no scheme, one can optionally + set up a type + + server that maps type URLs to message definitions as + follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based + on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in + the official + + protobuf release, and it is not used for type URLs + beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) + might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer + message along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values + in the form + + of utility functions or additional generated methods of the + Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := anypb.New(foo) + if err != nil { + ... + } + ... + foo := &pb.Foo{} + if err := any.UnmarshalTo(foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by + default use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the + last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield + type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with + an + + additional field `@type` which contains the type URL. + Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom + JSON + + representation, that representation will be embedded adding + a field + + `value` which holds the custom JSON in addition to the + `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + parameters: + - name: cons_address + description: cons_address is the validator cons address to query the account for. + in: path + required: true + type: string + tags: + - Query +definitions: + ethermint.evm.v1.ChainConfig: + type: object + properties: + homestead_block: + type: string + title: Homestead switch block (nil no fork, 0 = already homestead) + dao_fork_block: + type: string + title: TheDAO hard-fork switch block (nil no fork) + dao_fork_support: + type: boolean + title: Whether the nodes supports or opposes the DAO hard-fork + eip150_block: + type: string + title: >- + EIP150 implements the Gas price changes + + (https://github.com/ethereum/EIPs/issues/150) EIP150 HF block (nil no + fork) + eip150_hash: + type: string + title: >- + EIP150 HF hash (needed for header only clients as only gas pricing + changed) + eip155_block: + type: string + title: EIP155Block HF block + eip158_block: + type: string + title: EIP158 HF block + byzantium_block: + type: string + title: Byzantium switch block (nil no fork, 0 = already on byzantium) + constantinople_block: + type: string + title: Constantinople switch block (nil no fork, 0 = already activated) + petersburg_block: + type: string + title: Petersburg switch block (nil same as Constantinople) + istanbul_block: + type: string + title: Istanbul switch block (nil no fork, 0 = already on istanbul) + muir_glacier_block: + type: string + title: >- + Eip-2384 (bomb delay) switch block (nil no fork, 0 = already + activated) + berlin_block: + type: string + title: Berlin switch block (nil = no fork, 0 = already on berlin) + london_block: + type: string + title: London switch block (nil = no fork, 0 = already on london) + arrow_glacier_block: + type: string + title: >- + Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already + activated) + gray_glacier_block: + type: string + title: >- + EIP-5133 (bomb delay) switch block (nil = no fork, 0 = already + activated) + merge_netsplit_block: + type: string + title: Virtual fork after The Merge to use as a network splitter + description: >- + ChainConfig defines the Ethereum ChainConfig parameters using *sdk.Int + values + + instead of *big.Int. + ethermint.evm.v1.EstimateGasResponse: + type: object + properties: + gas: + type: string + format: uint64 + title: the estimated gas + title: EstimateGasResponse defines EstimateGas response + ethermint.evm.v1.Log: + type: object + properties: + address: + type: string + title: address of the contract that generated the event + topics: + type: array + items: + type: string + description: list of topics provided by the contract. + data: + type: string + format: byte + title: supplied by the contract, usually ABI-encoded + block_number: + type: string + format: uint64 + title: block in which the transaction was included + tx_hash: + type: string + title: hash of the transaction + tx_index: + type: string + format: uint64 + title: index of the transaction in the block + block_hash: + type: string + title: hash of the block in which the transaction was included + index: + type: string + format: uint64 + title: index of the log in the block + removed: + type: boolean + description: >- + The Removed field is true if this log was reverted due to a chain + + reorganisation. You must pay attention to this field if you receive + logs + + through a filter query. + description: >- + Log represents an protobuf compatible Ethereum Log that defines a contract + + log event. These events are generated by the LOG opcode and stored/indexed + by + + the node. + ethermint.evm.v1.MsgEthereumTx: + type: object + properties: + data: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of the + serialized + + protocol buffer message. This string must contain at least + + one "/" character. The last segment of the URL's path must + represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in a + canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary all types + that they + + expect it to use in the context of Any. However, for URLs which + use the + + scheme `http`, `https`, or no scheme, one can optionally set up a + type + + server that maps type URLs to message definitions as follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in the + official + + protobuf release, and it is not used for type URLs beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above specified + type. + description: >- + `Any` contains an arbitrary serialized protocol buffer message along + with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values in the + form + + of utility functions or additional generated methods of the Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := anypb.New(foo) + if err != nil { + ... + } + ... + foo := &pb.Foo{} + if err := any.UnmarshalTo(foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by default use + + 'type.googleapis.com/full.type.name' as the type URL and the unpack + + methods only use the fully qualified type name after the last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with an + + additional field `@type` which contains the type URL. Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom JSON + + representation, that representation will be embedded adding a field + + `value` which holds the custom JSON in addition to the `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + title: inner transaction data + size: + type: number + format: double + title: 'DEPRECATED: encoded storage size of the transaction' + hash: + type: string + title: transaction hash in hex format + from: + type: string + title: |- + ethereum signer address in hex format. This address value is checked + against the address derived from the signature (V, R, S) using the + secp256k1 elliptic curve + description: MsgEthereumTx encapsulates an Ethereum transaction as an SDK message. + ethermint.evm.v1.MsgEthereumTxResponse: + type: object + properties: + hash: + type: string + title: |- + ethereum transaction hash in hex format. This hash differs from the + Tendermint sha256 hash of the transaction bytes. See + https://github.com/tendermint/tendermint/issues/6539 for reference + logs: + type: array + items: + type: object + properties: + address: + type: string + title: address of the contract that generated the event + topics: + type: array + items: + type: string + description: list of topics provided by the contract. + data: + type: string + format: byte + title: supplied by the contract, usually ABI-encoded + block_number: + type: string + format: uint64 + title: block in which the transaction was included + tx_hash: + type: string + title: hash of the transaction + tx_index: + type: string + format: uint64 + title: index of the transaction in the block + block_hash: + type: string + title: hash of the block in which the transaction was included + index: + type: string + format: uint64 + title: index of the log in the block + removed: + type: boolean + description: >- + The Removed field is true if this log was reverted due to a + chain + + reorganisation. You must pay attention to this field if you + receive logs + + through a filter query. + description: >- + Log represents an protobuf compatible Ethereum Log that defines a + contract + + log event. These events are generated by the LOG opcode and + stored/indexed by + + the node. + description: |- + logs contains the transaction hash and the proto-compatible ethereum + logs. + ret: + type: string + format: byte + title: |- + returned data from evm function (result or data supplied with revert + opcode) + vm_error: + type: string + title: vm error is the error returned by vm execution + gas_used: + type: string + format: uint64 + title: gas consumed by the transaction + description: MsgEthereumTxResponse defines the Msg/EthereumTx response type. + ethermint.evm.v1.Params: + type: object + properties: + evm_denom: + type: string + description: |- + evm denom represents the token denomination used to run the EVM state + transitions. + enable_create: + type: boolean + title: >- + enable create toggles state transitions that use the vm.Create + function + enable_call: + type: boolean + title: enable call toggles state transitions that use the vm.Call function + extra_eips: + type: array + items: + type: string + format: int64 + title: extra eips defines the additional EIPs for the vm.Config + chain_config: + title: chain config defines the EVM chain configuration parameters + type: object + properties: + homestead_block: + type: string + title: Homestead switch block (nil no fork, 0 = already homestead) + dao_fork_block: + type: string + title: TheDAO hard-fork switch block (nil no fork) + dao_fork_support: + type: boolean + title: Whether the nodes supports or opposes the DAO hard-fork + eip150_block: + type: string + title: >- + EIP150 implements the Gas price changes + + (https://github.com/ethereum/EIPs/issues/150) EIP150 HF block (nil + no fork) + eip150_hash: + type: string + title: >- + EIP150 HF hash (needed for header only clients as only gas pricing + changed) + eip155_block: + type: string + title: EIP155Block HF block + eip158_block: + type: string + title: EIP158 HF block + byzantium_block: + type: string + title: Byzantium switch block (nil no fork, 0 = already on byzantium) + constantinople_block: + type: string + title: Constantinople switch block (nil no fork, 0 = already activated) + petersburg_block: + type: string + title: Petersburg switch block (nil same as Constantinople) + istanbul_block: + type: string + title: Istanbul switch block (nil no fork, 0 = already on istanbul) + muir_glacier_block: + type: string + title: >- + Eip-2384 (bomb delay) switch block (nil no fork, 0 = already + activated) + berlin_block: + type: string + title: Berlin switch block (nil = no fork, 0 = already on berlin) + london_block: + type: string + title: London switch block (nil = no fork, 0 = already on london) + arrow_glacier_block: + type: string + title: >- + Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already + activated) + gray_glacier_block: + type: string + title: >- + EIP-5133 (bomb delay) switch block (nil = no fork, 0 = already + activated) + merge_netsplit_block: + type: string + title: Virtual fork after The Merge to use as a network splitter + description: >- + ChainConfig defines the Ethereum ChainConfig parameters using *sdk.Int + values + + instead of *big.Int. + allow_unprotected_txs: + type: boolean + description: >- + Allow unprotected transactions defines if replay-protected (i.e non + EIP155 + + signed) transactions can be executed on the state machine. + title: Params defines the EVM module parameters + ethermint.evm.v1.QueryAccountResponse: + type: object + properties: + balance: + type: string + description: balance is the balance of the EVM denomination. + code_hash: + type: string + description: code hash is the hex-formatted code bytes from the EOA. + nonce: + type: string + format: uint64 + description: nonce is the account's sequence number. + description: >- + QueryAccountResponse is the response type for the Query/Account RPC + method. + ethermint.evm.v1.QueryBalanceResponse: + type: object + properties: + balance: + type: string + description: balance is the balance of the EVM denomination. + description: >- + QueryBalanceResponse is the response type for the Query/Balance RPC + method. + ethermint.evm.v1.QueryBaseFeeResponse: + type: object + properties: + base_fee: + type: string + description: BaseFeeResponse returns the EIP1559 base fee. + ethermint.evm.v1.QueryCodeResponse: + type: object + properties: + code: + type: string + format: byte + description: code represents the code bytes from an ethereum address. + description: |- + QueryCodeResponse is the response type for the Query/Code RPC + method. + ethermint.evm.v1.QueryCosmosAccountResponse: + type: object + properties: + cosmos_address: + type: string + description: cosmos_address is the cosmos address of the account. + sequence: + type: string + format: uint64 + description: sequence is the account's sequence number. + account_number: + type: string + format: uint64 + title: account_number is the account numbert + description: >- + QueryCosmosAccountResponse is the response type for the + Query/CosmosAccount + + RPC method. + ethermint.evm.v1.QueryParamsResponse: + type: object + properties: + params: + description: params define the evm module parameters. + type: object + properties: + evm_denom: + type: string + description: >- + evm denom represents the token denomination used to run the EVM + state + + transitions. + enable_create: + type: boolean + title: >- + enable create toggles state transitions that use the vm.Create + function + enable_call: + type: boolean + title: >- + enable call toggles state transitions that use the vm.Call + function + extra_eips: + type: array + items: + type: string + format: int64 + title: extra eips defines the additional EIPs for the vm.Config + chain_config: + title: chain config defines the EVM chain configuration parameters + type: object + properties: + homestead_block: + type: string + title: Homestead switch block (nil no fork, 0 = already homestead) + dao_fork_block: + type: string + title: TheDAO hard-fork switch block (nil no fork) + dao_fork_support: + type: boolean + title: Whether the nodes supports or opposes the DAO hard-fork + eip150_block: + type: string + title: >- + EIP150 implements the Gas price changes + + (https://github.com/ethereum/EIPs/issues/150) EIP150 HF block + (nil no fork) + eip150_hash: + type: string + title: >- + EIP150 HF hash (needed for header only clients as only gas + pricing changed) + eip155_block: + type: string + title: EIP155Block HF block + eip158_block: + type: string + title: EIP158 HF block + byzantium_block: + type: string + title: Byzantium switch block (nil no fork, 0 = already on byzantium) + constantinople_block: + type: string + title: >- + Constantinople switch block (nil no fork, 0 = already + activated) + petersburg_block: + type: string + title: Petersburg switch block (nil same as Constantinople) + istanbul_block: + type: string + title: Istanbul switch block (nil no fork, 0 = already on istanbul) + muir_glacier_block: + type: string + title: >- + Eip-2384 (bomb delay) switch block (nil no fork, 0 = already + activated) + berlin_block: + type: string + title: Berlin switch block (nil = no fork, 0 = already on berlin) + london_block: + type: string + title: London switch block (nil = no fork, 0 = already on london) + arrow_glacier_block: + type: string + title: >- + Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already + activated) + gray_glacier_block: + type: string + title: >- + EIP-5133 (bomb delay) switch block (nil = no fork, 0 = already + activated) + merge_netsplit_block: + type: string + title: Virtual fork after The Merge to use as a network splitter + description: >- + ChainConfig defines the Ethereum ChainConfig parameters using + *sdk.Int values + + instead of *big.Int. + allow_unprotected_txs: + type: boolean + description: >- + Allow unprotected transactions defines if replay-protected (i.e + non EIP155 + + signed) transactions can be executed on the state machine. + title: Params defines the EVM module parameters + description: >- + QueryParamsResponse defines the response type for querying x/evm + parameters. + ethermint.evm.v1.QueryStorageResponse: + type: object + properties: + value: + type: string + description: >- + key defines the storage state value hash associated with the given + key. + description: |- + QueryStorageResponse is the response type for the Query/Storage RPC + method. + ethermint.evm.v1.QueryTraceBlockResponse: + type: object + properties: + data: + type: string + format: byte + title: QueryTraceBlockResponse defines TraceBlock response + ethermint.evm.v1.QueryTraceTxResponse: + type: object + properties: + data: + type: string + format: byte + title: response serialized in bytes + title: QueryTraceTxResponse defines TraceTx response + ethermint.evm.v1.QueryValidatorAccountResponse: + type: object + properties: + account_address: + type: string + description: account_address is the cosmos address of the account in bech32 format. + sequence: + type: string + format: uint64 + description: sequence is the account's sequence number. + account_number: + type: string + format: uint64 + title: account_number is the account number + description: |- + QueryValidatorAccountResponse is the response type for the + Query/ValidatorAccount RPC method. + ethermint.evm.v1.TraceConfig: + type: object + properties: + tracer: + type: string + title: custom javascript tracer + timeout: + type: string + title: >- + overrides the default timeout of 5 seconds for JavaScript-based + tracing + + calls + reexec: + type: string + format: uint64 + title: number of blocks the tracer is willing to go back + disable_stack: + type: boolean + title: disable stack capture + disable_storage: + type: boolean + title: disable storage capture + debug: + type: boolean + title: print output during capture end + limit: + type: integer + format: int32 + title: maximum length of output, but zero means unlimited + overrides: + title: >- + Chain overrides, can be used to execute a trace using future fork + rules + type: object + properties: + homestead_block: + type: string + title: Homestead switch block (nil no fork, 0 = already homestead) + dao_fork_block: + type: string + title: TheDAO hard-fork switch block (nil no fork) + dao_fork_support: + type: boolean + title: Whether the nodes supports or opposes the DAO hard-fork + eip150_block: + type: string + title: >- + EIP150 implements the Gas price changes + + (https://github.com/ethereum/EIPs/issues/150) EIP150 HF block (nil + no fork) + eip150_hash: + type: string + title: >- + EIP150 HF hash (needed for header only clients as only gas pricing + changed) + eip155_block: + type: string + title: EIP155Block HF block + eip158_block: + type: string + title: EIP158 HF block + byzantium_block: + type: string + title: Byzantium switch block (nil no fork, 0 = already on byzantium) + constantinople_block: + type: string + title: Constantinople switch block (nil no fork, 0 = already activated) + petersburg_block: + type: string + title: Petersburg switch block (nil same as Constantinople) + istanbul_block: + type: string + title: Istanbul switch block (nil no fork, 0 = already on istanbul) + muir_glacier_block: + type: string + title: >- + Eip-2384 (bomb delay) switch block (nil no fork, 0 = already + activated) + berlin_block: + type: string + title: Berlin switch block (nil = no fork, 0 = already on berlin) + london_block: + type: string + title: London switch block (nil = no fork, 0 = already on london) + arrow_glacier_block: + type: string + title: >- + Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already + activated) + gray_glacier_block: + type: string + title: >- + EIP-5133 (bomb delay) switch block (nil = no fork, 0 = already + activated) + merge_netsplit_block: + type: string + title: Virtual fork after The Merge to use as a network splitter + description: >- + ChainConfig defines the Ethereum ChainConfig parameters using *sdk.Int + values + + instead of *big.Int. + enable_memory: + type: boolean + title: enable memory capture + enable_return_data: + type: boolean + title: enable return data capture + tracer_json_config: + type: string + title: tracer config + description: TraceConfig holds extra parameters to trace functions. + google.protobuf.Any: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of the + serialized + + protocol buffer message. This string must contain at least + + one "/" character. The last segment of the URL's path must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in a canonical + form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary all types that + they + + expect it to use in the context of Any. However, for URLs which use + the + + scheme `http`, `https`, or no scheme, one can optionally set up a type + + server that maps type URLs to message definitions as follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in the official + + protobuf release, and it is not used for type URLs beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above specified + type. + description: >- + `Any` contains an arbitrary serialized protocol buffer message along with + a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values in the form + + of utility functions or additional generated methods of the Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := anypb.New(foo) + if err != nil { + ... + } + ... + foo := &pb.Foo{} + if err := any.UnmarshalTo(foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by default use + + 'type.googleapis.com/full.type.name' as the type URL and the unpack + + methods only use the fully qualified type name after the last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with an + + additional field `@type` which contains the type URL. Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom JSON + + representation, that representation will be embedded adding a field + + `value` which holds the custom JSON in addition to the `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + grpc.gateway.runtime.Error: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of the + serialized + + protocol buffer message. This string must contain at least + + one "/" character. The last segment of the URL's path must + represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in a + canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary all types + that they + + expect it to use in the context of Any. However, for URLs which + use the + + scheme `http`, `https`, or no scheme, one can optionally set up + a type + + server that maps type URLs to message definitions as follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in the + official + + protobuf release, and it is not used for type URLs beginning + with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) might + be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer message along + with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values in the + form + + of utility functions or additional generated methods of the Any + type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := anypb.New(foo) + if err != nil { + ... + } + ... + foo := &pb.Foo{} + if err := any.UnmarshalTo(foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by default use + + 'type.googleapis.com/full.type.name' as the type URL and the unpack + + methods only use the fully qualified type name after the last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with an + + additional field `@type` which contains the type URL. Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom JSON + + representation, that representation will be embedded adding a field + + `value` which holds the custom JSON in addition to the `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } diff --git a/client/docs/swagger-ui/swagger.yaml b/client/docs/swagger-ui/swagger.yaml index 173ec859..637c815d 100644 --- a/client/docs/swagger-ui/swagger.yaml +++ b/client/docs/swagger-ui/swagger.yaml @@ -12019,6 +12019,163 @@ paths: format: byte tags: - Liquid + /kava/precisebank/v1/fractional_balance/{address}: + get: + summary: >- + FractionalBalance returns only the fractional balance of an address. + This + + does not include any integer balance. + operationId: PrecisebankFractionalBalance + responses: + '200': + description: A successful response. + schema: + type: object + properties: + fractional_balance: + description: fractional_balance is the fractional balance of the address. + type: object + properties: + denom: + type: string + amount: + type: string + description: >- + QueryFractionalBalanceResponse defines the response type for + Query/FractionalBalance method. + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + value: + type: string + format: byte + parameters: + - name: address + description: address is the account address to query fractional balance for. + in: path + required: true + type: string + tags: + - Precisebank + /kava/precisebank/v1/remainder: + get: + summary: |- + Remainder returns the amount backed by the reserve, but not yet owned by + any account, i.e. not in circulation. + operationId: PrecisebankRemainder + responses: + '200': + description: A successful response. + schema: + type: object + properties: + remainder: + description: >- + remainder is the amount backed by the reserve, but not yet + owned by any + + account, i.e. not in circulation. + type: object + properties: + denom: + type: string + amount: + type: string + description: >- + QueryRemainderResponse defines the response type for + Query/Remainder method. + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + value: + type: string + format: byte + tags: + - Precisebank + /kava/precisebank/v1/total_fractional_balances: + get: + summary: |- + TotalFractionalBalances returns the total sum of all fractional balances + managed by the precisebank module. + operationId: PrecisebankTotalFractionalBalances + responses: + '200': + description: A successful response. + schema: + type: object + properties: + total: + description: >- + total is the total sum of all fractional balances managed by + the precisebank + + module. + type: object + properties: + denom: + type: string + amount: + type: string + description: >- + QueryTotalFractionalBalancesResponse defines the response type for + Query/TotalFractionalBalances method. + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + value: + type: string + format: byte + tags: + - Precisebank /kava/pricefeed/v1beta1/markets: get: summary: Markets queries all markets @@ -51555,6 +51712,3301 @@ paths: type: boolean tags: - IBC + /ethermint/evm/v1/account/{address}: + get: + summary: Account queries an Ethereum account. + operationId: EthermintAccount + responses: + '200': + description: A successful response. + schema: + type: object + properties: + balance: + type: string + description: balance is the balance of the EVM denomination. + code_hash: + type: string + description: code hash is the hex-formatted code bytes from the EOA. + nonce: + type: string + format: uint64 + description: nonce is the account's sequence number. + description: >- + QueryAccountResponse is the response type for the Query/Account + RPC method. + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of + the serialized + + protocol buffer message. This string must contain at + least + + one "/" character. The last segment of the URL's path + must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in + a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary + all types that they + + expect it to use in the context of Any. However, for + URLs which use the + + scheme `http`, `https`, or no scheme, one can optionally + set up a type + + server that maps type URLs to message definitions as + follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based + on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in + the official + + protobuf release, and it is not used for type URLs + beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) + might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer + message along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values + in the form + + of utility functions or additional generated methods of the + Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := anypb.New(foo) + if err != nil { + ... + } + ... + foo := &pb.Foo{} + if err := any.UnmarshalTo(foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by + default use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the + last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield + type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with + an + + additional field `@type` which contains the type URL. + Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom + JSON + + representation, that representation will be embedded adding + a field + + `value` which holds the custom JSON in addition to the + `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + parameters: + - name: address + description: address is the ethereum hex address to query the account for. + in: path + required: true + type: string + tags: + - Ethermint + /ethermint/evm/v1/balances/{address}: + get: + summary: |- + Balance queries the balance of a the EVM denomination for a single + EthAccount. + operationId: EthermintBalance + responses: + '200': + description: A successful response. + schema: + type: object + properties: + balance: + type: string + description: balance is the balance of the EVM denomination. + description: >- + QueryBalanceResponse is the response type for the Query/Balance + RPC method. + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of + the serialized + + protocol buffer message. This string must contain at + least + + one "/" character. The last segment of the URL's path + must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in + a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary + all types that they + + expect it to use in the context of Any. However, for + URLs which use the + + scheme `http`, `https`, or no scheme, one can optionally + set up a type + + server that maps type URLs to message definitions as + follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based + on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in + the official + + protobuf release, and it is not used for type URLs + beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) + might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer + message along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values + in the form + + of utility functions or additional generated methods of the + Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := anypb.New(foo) + if err != nil { + ... + } + ... + foo := &pb.Foo{} + if err := any.UnmarshalTo(foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by + default use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the + last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield + type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with + an + + additional field `@type` which contains the type URL. + Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom + JSON + + representation, that representation will be embedded adding + a field + + `value` which holds the custom JSON in addition to the + `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + parameters: + - name: address + description: address is the ethereum hex address to query the balance for. + in: path + required: true + type: string + tags: + - Ethermint + /ethermint/evm/v1/base_fee: + get: + summary: >- + BaseFee queries the base fee of the parent block of the current block, + + it's similar to feemarket module's method, but also checks london + hardfork status. + operationId: EthermintBaseFee + responses: + '200': + description: A successful response. + schema: + type: object + properties: + base_fee: + type: string + description: BaseFeeResponse returns the EIP1559 base fee. + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of + the serialized + + protocol buffer message. This string must contain at + least + + one "/" character. The last segment of the URL's path + must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in + a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary + all types that they + + expect it to use in the context of Any. However, for + URLs which use the + + scheme `http`, `https`, or no scheme, one can optionally + set up a type + + server that maps type URLs to message definitions as + follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based + on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in + the official + + protobuf release, and it is not used for type URLs + beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) + might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer + message along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values + in the form + + of utility functions or additional generated methods of the + Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := anypb.New(foo) + if err != nil { + ... + } + ... + foo := &pb.Foo{} + if err := any.UnmarshalTo(foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by + default use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the + last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield + type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with + an + + additional field `@type` which contains the type URL. + Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom + JSON + + representation, that representation will be embedded adding + a field + + `value` which holds the custom JSON in addition to the + `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + tags: + - Ethermint + /ethermint/evm/v1/codes/{address}: + get: + summary: Code queries the balance of all coins for a single account. + operationId: EthermintCode + responses: + '200': + description: A successful response. + schema: + type: object + properties: + code: + type: string + format: byte + description: code represents the code bytes from an ethereum address. + description: |- + QueryCodeResponse is the response type for the Query/Code RPC + method. + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of + the serialized + + protocol buffer message. This string must contain at + least + + one "/" character. The last segment of the URL's path + must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in + a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary + all types that they + + expect it to use in the context of Any. However, for + URLs which use the + + scheme `http`, `https`, or no scheme, one can optionally + set up a type + + server that maps type URLs to message definitions as + follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based + on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in + the official + + protobuf release, and it is not used for type URLs + beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) + might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer + message along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values + in the form + + of utility functions or additional generated methods of the + Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := anypb.New(foo) + if err != nil { + ... + } + ... + foo := &pb.Foo{} + if err := any.UnmarshalTo(foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by + default use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the + last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield + type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with + an + + additional field `@type` which contains the type URL. + Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom + JSON + + representation, that representation will be embedded adding + a field + + `value` which holds the custom JSON in addition to the + `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + parameters: + - name: address + description: address is the ethereum hex address to query the code for. + in: path + required: true + type: string + tags: + - Ethermint + /ethermint/evm/v1/cosmos_account/{address}: + get: + summary: CosmosAccount queries an Ethereum account's Cosmos Address. + operationId: EthermintCosmosAccount + responses: + '200': + description: A successful response. + schema: + type: object + properties: + cosmos_address: + type: string + description: cosmos_address is the cosmos address of the account. + sequence: + type: string + format: uint64 + description: sequence is the account's sequence number. + account_number: + type: string + format: uint64 + title: account_number is the account numbert + description: >- + QueryCosmosAccountResponse is the response type for the + Query/CosmosAccount + + RPC method. + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of + the serialized + + protocol buffer message. This string must contain at + least + + one "/" character. The last segment of the URL's path + must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in + a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary + all types that they + + expect it to use in the context of Any. However, for + URLs which use the + + scheme `http`, `https`, or no scheme, one can optionally + set up a type + + server that maps type URLs to message definitions as + follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based + on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in + the official + + protobuf release, and it is not used for type URLs + beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) + might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer + message along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values + in the form + + of utility functions or additional generated methods of the + Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := anypb.New(foo) + if err != nil { + ... + } + ... + foo := &pb.Foo{} + if err := any.UnmarshalTo(foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by + default use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the + last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield + type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with + an + + additional field `@type` which contains the type URL. + Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom + JSON + + representation, that representation will be embedded adding + a field + + `value` which holds the custom JSON in addition to the + `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + parameters: + - name: address + description: address is the ethereum hex address to query the account for. + in: path + required: true + type: string + tags: + - Ethermint + /ethermint/evm/v1/estimate_gas: + get: + summary: EstimateGas implements the `eth_estimateGas` rpc api + operationId: EthermintEstimateGas + responses: + '200': + description: A successful response. + schema: + type: object + properties: + gas: + type: string + format: uint64 + title: the estimated gas + title: EstimateGasResponse defines EstimateGas response + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of + the serialized + + protocol buffer message. This string must contain at + least + + one "/" character. The last segment of the URL's path + must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in + a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary + all types that they + + expect it to use in the context of Any. However, for + URLs which use the + + scheme `http`, `https`, or no scheme, one can optionally + set up a type + + server that maps type URLs to message definitions as + follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based + on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in + the official + + protobuf release, and it is not used for type URLs + beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) + might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer + message along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values + in the form + + of utility functions or additional generated methods of the + Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := anypb.New(foo) + if err != nil { + ... + } + ... + foo := &pb.Foo{} + if err := any.UnmarshalTo(foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by + default use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the + last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield + type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with + an + + additional field `@type` which contains the type URL. + Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom + JSON + + representation, that representation will be embedded adding + a field + + `value` which holds the custom JSON in addition to the + `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + parameters: + - name: args + description: same json format as the json rpc api. + in: query + required: false + type: string + format: byte + - name: gas_cap + description: the default gas cap to be used. + in: query + required: false + type: string + format: uint64 + - name: proposer_address + description: the proposer of the requested block. + in: query + required: false + type: string + format: byte + - name: chain_id + description: the eip155 chain id parsed from the requested block header. + in: query + required: false + type: string + format: int64 + tags: + - Ethermint + /ethermint/evm/v1/eth_call: + get: + summary: EthCall implements the `eth_call` rpc api + operationId: EthermintEthCall + responses: + '200': + description: A successful response. + schema: + type: object + properties: + hash: + type: string + title: >- + ethereum transaction hash in hex format. This hash differs + from the + + Tendermint sha256 hash of the transaction bytes. See + + https://github.com/tendermint/tendermint/issues/6539 for + reference + logs: + type: array + items: + type: object + properties: + address: + type: string + title: address of the contract that generated the event + topics: + type: array + items: + type: string + description: list of topics provided by the contract. + data: + type: string + format: byte + title: supplied by the contract, usually ABI-encoded + block_number: + type: string + format: uint64 + title: block in which the transaction was included + tx_hash: + type: string + title: hash of the transaction + tx_index: + type: string + format: uint64 + title: index of the transaction in the block + block_hash: + type: string + title: hash of the block in which the transaction was included + index: + type: string + format: uint64 + title: index of the log in the block + removed: + type: boolean + description: >- + The Removed field is true if this log was reverted due + to a chain + + reorganisation. You must pay attention to this field if + you receive logs + + through a filter query. + description: >- + Log represents an protobuf compatible Ethereum Log that + defines a contract + + log event. These events are generated by the LOG opcode and + stored/indexed by + + the node. + description: >- + logs contains the transaction hash and the proto-compatible + ethereum + + logs. + ret: + type: string + format: byte + title: >- + returned data from evm function (result or data supplied with + revert + + opcode) + vm_error: + type: string + title: vm error is the error returned by vm execution + gas_used: + type: string + format: uint64 + title: gas consumed by the transaction + description: MsgEthereumTxResponse defines the Msg/EthereumTx response type. + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of + the serialized + + protocol buffer message. This string must contain at + least + + one "/" character. The last segment of the URL's path + must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in + a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary + all types that they + + expect it to use in the context of Any. However, for + URLs which use the + + scheme `http`, `https`, or no scheme, one can optionally + set up a type + + server that maps type URLs to message definitions as + follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based + on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in + the official + + protobuf release, and it is not used for type URLs + beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) + might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer + message along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values + in the form + + of utility functions or additional generated methods of the + Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := anypb.New(foo) + if err != nil { + ... + } + ... + foo := &pb.Foo{} + if err := any.UnmarshalTo(foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by + default use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the + last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield + type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with + an + + additional field `@type` which contains the type URL. + Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom + JSON + + representation, that representation will be embedded adding + a field + + `value` which holds the custom JSON in addition to the + `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + parameters: + - name: args + description: same json format as the json rpc api. + in: query + required: false + type: string + format: byte + - name: gas_cap + description: the default gas cap to be used. + in: query + required: false + type: string + format: uint64 + - name: proposer_address + description: the proposer of the requested block. + in: query + required: false + type: string + format: byte + - name: chain_id + description: the eip155 chain id parsed from the requested block header. + in: query + required: false + type: string + format: int64 + tags: + - Ethermint + /ethermint/evm/v1/params: + get: + summary: Params queries the parameters of x/evm module. + operationId: EthermintEvmParams + responses: + '200': + description: A successful response. + schema: + type: object + properties: + params: + description: params define the evm module parameters. + type: object + properties: + evm_denom: + type: string + description: >- + evm denom represents the token denomination used to run + the EVM state + + transitions. + enable_create: + type: boolean + title: >- + enable create toggles state transitions that use the + vm.Create function + enable_call: + type: boolean + title: >- + enable call toggles state transitions that use the vm.Call + function + extra_eips: + type: array + items: + type: string + format: int64 + title: extra eips defines the additional EIPs for the vm.Config + chain_config: + title: >- + chain config defines the EVM chain configuration + parameters + type: object + properties: + homestead_block: + type: string + title: >- + Homestead switch block (nil no fork, 0 = already + homestead) + dao_fork_block: + type: string + title: TheDAO hard-fork switch block (nil no fork) + dao_fork_support: + type: boolean + title: >- + Whether the nodes supports or opposes the DAO + hard-fork + eip150_block: + type: string + title: >- + EIP150 implements the Gas price changes + + (https://github.com/ethereum/EIPs/issues/150) EIP150 + HF block (nil no fork) + eip150_hash: + type: string + title: >- + EIP150 HF hash (needed for header only clients as only + gas pricing changed) + eip155_block: + type: string + title: EIP155Block HF block + eip158_block: + type: string + title: EIP158 HF block + byzantium_block: + type: string + title: >- + Byzantium switch block (nil no fork, 0 = already on + byzantium) + constantinople_block: + type: string + title: >- + Constantinople switch block (nil no fork, 0 = already + activated) + petersburg_block: + type: string + title: Petersburg switch block (nil same as Constantinople) + istanbul_block: + type: string + title: >- + Istanbul switch block (nil no fork, 0 = already on + istanbul) + muir_glacier_block: + type: string + title: >- + Eip-2384 (bomb delay) switch block (nil no fork, 0 = + already activated) + berlin_block: + type: string + title: >- + Berlin switch block (nil = no fork, 0 = already on + berlin) + london_block: + type: string + title: >- + London switch block (nil = no fork, 0 = already on + london) + arrow_glacier_block: + type: string + title: >- + Eip-4345 (bomb delay) switch block (nil = no fork, 0 = + already activated) + gray_glacier_block: + type: string + title: >- + EIP-5133 (bomb delay) switch block (nil = no fork, 0 = + already activated) + merge_netsplit_block: + type: string + title: >- + Virtual fork after The Merge to use as a network + splitter + description: >- + ChainConfig defines the Ethereum ChainConfig parameters + using *sdk.Int values + + instead of *big.Int. + allow_unprotected_txs: + type: boolean + description: >- + Allow unprotected transactions defines if replay-protected + (i.e non EIP155 + + signed) transactions can be executed on the state machine. + title: Params defines the EVM module parameters + description: >- + QueryParamsResponse defines the response type for querying x/evm + parameters. + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of + the serialized + + protocol buffer message. This string must contain at + least + + one "/" character. The last segment of the URL's path + must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in + a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary + all types that they + + expect it to use in the context of Any. However, for + URLs which use the + + scheme `http`, `https`, or no scheme, one can optionally + set up a type + + server that maps type URLs to message definitions as + follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based + on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in + the official + + protobuf release, and it is not used for type URLs + beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) + might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer + message along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values + in the form + + of utility functions or additional generated methods of the + Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := anypb.New(foo) + if err != nil { + ... + } + ... + foo := &pb.Foo{} + if err := any.UnmarshalTo(foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by + default use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the + last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield + type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with + an + + additional field `@type` which contains the type URL. + Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom + JSON + + representation, that representation will be embedded adding + a field + + `value` which holds the custom JSON in addition to the + `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + tags: + - Ethermint + /ethermint/evm/v1/storage/{address}/{key}: + get: + summary: Storage queries the balance of all coins for a single account. + operationId: EthermintStorage + responses: + '200': + description: A successful response. + schema: + type: object + properties: + value: + type: string + description: >- + key defines the storage state value hash associated with the + given key. + description: >- + QueryStorageResponse is the response type for the Query/Storage + RPC + + method. + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of + the serialized + + protocol buffer message. This string must contain at + least + + one "/" character. The last segment of the URL's path + must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in + a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary + all types that they + + expect it to use in the context of Any. However, for + URLs which use the + + scheme `http`, `https`, or no scheme, one can optionally + set up a type + + server that maps type URLs to message definitions as + follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based + on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in + the official + + protobuf release, and it is not used for type URLs + beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) + might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer + message along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values + in the form + + of utility functions or additional generated methods of the + Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := anypb.New(foo) + if err != nil { + ... + } + ... + foo := &pb.Foo{} + if err := any.UnmarshalTo(foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by + default use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the + last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield + type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with + an + + additional field `@type` which contains the type URL. + Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom + JSON + + representation, that representation will be embedded adding + a field + + `value` which holds the custom JSON in addition to the + `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + parameters: + - name: address + description: >- + / address is the ethereum hex address to query the storage state + for. + in: path + required: true + type: string + - name: key + description: key defines the key of the storage state + in: path + required: true + type: string + tags: + - Ethermint + /ethermint/evm/v1/trace_block: + get: + summary: >- + TraceBlock implements the `debug_traceBlockByNumber` and + `debug_traceBlockByHash` rpc api + operationId: EthermintTraceBlock + responses: + '200': + description: A successful response. + schema: + type: object + properties: + data: + type: string + format: byte + title: QueryTraceBlockResponse defines TraceBlock response + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of + the serialized + + protocol buffer message. This string must contain at + least + + one "/" character. The last segment of the URL's path + must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in + a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary + all types that they + + expect it to use in the context of Any. However, for + URLs which use the + + scheme `http`, `https`, or no scheme, one can optionally + set up a type + + server that maps type URLs to message definitions as + follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based + on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in + the official + + protobuf release, and it is not used for type URLs + beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) + might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer + message along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values + in the form + + of utility functions or additional generated methods of the + Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := anypb.New(foo) + if err != nil { + ... + } + ... + foo := &pb.Foo{} + if err := any.UnmarshalTo(foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by + default use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the + last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield + type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with + an + + additional field `@type` which contains the type URL. + Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom + JSON + + representation, that representation will be embedded adding + a field + + `value` which holds the custom JSON in addition to the + `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + parameters: + - name: trace_config.tracer + description: custom javascript tracer. + in: query + required: false + type: string + - name: trace_config.timeout + description: >- + overrides the default timeout of 5 seconds for JavaScript-based + tracing + + calls. + in: query + required: false + type: string + - name: trace_config.reexec + description: number of blocks the tracer is willing to go back. + in: query + required: false + type: string + format: uint64 + - name: trace_config.disable_stack + description: disable stack capture. + in: query + required: false + type: boolean + - name: trace_config.disable_storage + description: disable storage capture. + in: query + required: false + type: boolean + - name: trace_config.debug + description: print output during capture end. + in: query + required: false + type: boolean + - name: trace_config.limit + description: maximum length of output, but zero means unlimited. + in: query + required: false + type: integer + format: int32 + - name: trace_config.overrides.homestead_block + description: Homestead switch block (nil no fork, 0 = already homestead). + in: query + required: false + type: string + - name: trace_config.overrides.dao_fork_block + description: TheDAO hard-fork switch block (nil no fork). + in: query + required: false + type: string + - name: trace_config.overrides.dao_fork_support + description: Whether the nodes supports or opposes the DAO hard-fork. + in: query + required: false + type: boolean + - name: trace_config.overrides.eip150_block + description: >- + EIP150 implements the Gas price changes + + (https://github.com/ethereum/EIPs/issues/150) EIP150 HF block (nil + no fork). + in: query + required: false + type: string + - name: trace_config.overrides.eip150_hash + description: >- + EIP150 HF hash (needed for header only clients as only gas pricing + changed). + in: query + required: false + type: string + - name: trace_config.overrides.eip155_block + description: EIP155Block HF block. + in: query + required: false + type: string + - name: trace_config.overrides.eip158_block + description: EIP158 HF block. + in: query + required: false + type: string + - name: trace_config.overrides.byzantium_block + description: Byzantium switch block (nil no fork, 0 = already on byzantium). + in: query + required: false + type: string + - name: trace_config.overrides.constantinople_block + description: Constantinople switch block (nil no fork, 0 = already activated). + in: query + required: false + type: string + - name: trace_config.overrides.petersburg_block + description: Petersburg switch block (nil same as Constantinople). + in: query + required: false + type: string + - name: trace_config.overrides.istanbul_block + description: Istanbul switch block (nil no fork, 0 = already on istanbul). + in: query + required: false + type: string + - name: trace_config.overrides.muir_glacier_block + description: >- + Eip-2384 (bomb delay) switch block (nil no fork, 0 = already + activated). + in: query + required: false + type: string + - name: trace_config.overrides.berlin_block + description: Berlin switch block (nil = no fork, 0 = already on berlin). + in: query + required: false + type: string + - name: trace_config.overrides.london_block + description: London switch block (nil = no fork, 0 = already on london). + in: query + required: false + type: string + - name: trace_config.overrides.arrow_glacier_block + description: >- + Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already + activated). + in: query + required: false + type: string + - name: trace_config.overrides.gray_glacier_block + description: >- + EIP-5133 (bomb delay) switch block (nil = no fork, 0 = already + activated). + in: query + required: false + type: string + - name: trace_config.overrides.merge_netsplit_block + description: Virtual fork after The Merge to use as a network splitter. + in: query + required: false + type: string + - name: trace_config.enable_memory + description: enable memory capture. + in: query + required: false + type: boolean + - name: trace_config.enable_return_data + description: enable return data capture. + in: query + required: false + type: boolean + - name: trace_config.tracer_json_config + description: tracer config. + in: query + required: false + type: string + - name: block_number + description: block number. + in: query + required: false + type: string + format: int64 + - name: block_hash + description: block hex hash. + in: query + required: false + type: string + - name: block_time + description: block time. + in: query + required: false + type: string + format: date-time + - name: proposer_address + description: the proposer of the requested block. + in: query + required: false + type: string + format: byte + - name: chain_id + description: the eip155 chain id parsed from the requested block header. + in: query + required: false + type: string + format: int64 + tags: + - Ethermint + /ethermint/evm/v1/trace_tx: + get: + summary: TraceTx implements the `debug_traceTransaction` rpc api + operationId: EthermintTraceTx + responses: + '200': + description: A successful response. + schema: + type: object + properties: + data: + type: string + format: byte + title: response serialized in bytes + title: QueryTraceTxResponse defines TraceTx response + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of + the serialized + + protocol buffer message. This string must contain at + least + + one "/" character. The last segment of the URL's path + must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in + a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary + all types that they + + expect it to use in the context of Any. However, for + URLs which use the + + scheme `http`, `https`, or no scheme, one can optionally + set up a type + + server that maps type URLs to message definitions as + follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based + on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in + the official + + protobuf release, and it is not used for type URLs + beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) + might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer + message along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values + in the form + + of utility functions or additional generated methods of the + Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := anypb.New(foo) + if err != nil { + ... + } + ... + foo := &pb.Foo{} + if err := any.UnmarshalTo(foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by + default use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the + last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield + type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with + an + + additional field `@type` which contains the type URL. + Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom + JSON + + representation, that representation will be embedded adding + a field + + `value` which holds the custom JSON in addition to the + `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + parameters: + - name: msg.data.type_url + description: >- + A URL/resource name that uniquely identifies the type of the + serialized + + protocol buffer message. This string must contain at least + + one "/" character. The last segment of the URL's path must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in a canonical + form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary all types that + they + + expect it to use in the context of Any. However, for URLs which use + the + + scheme `http`, `https`, or no scheme, one can optionally set up a + type + + server that maps type URLs to message definitions as follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in the official + + protobuf release, and it is not used for type URLs beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) might be + + used with implementation specific semantics. + in: query + required: false + type: string + - name: msg.data.value + description: >- + Must be a valid serialized protocol buffer of the above specified + type. + in: query + required: false + type: string + format: byte + - name: msg.size + description: 'DEPRECATED: encoded storage size of the transaction.' + in: query + required: false + type: number + format: double + - name: msg.hash + description: transaction hash in hex format. + in: query + required: false + type: string + - name: msg.from + description: |- + ethereum signer address in hex format. This address value is checked + against the address derived from the signature (V, R, S) using the + secp256k1 elliptic curve. + in: query + required: false + type: string + - name: trace_config.tracer + description: custom javascript tracer. + in: query + required: false + type: string + - name: trace_config.timeout + description: >- + overrides the default timeout of 5 seconds for JavaScript-based + tracing + + calls. + in: query + required: false + type: string + - name: trace_config.reexec + description: number of blocks the tracer is willing to go back. + in: query + required: false + type: string + format: uint64 + - name: trace_config.disable_stack + description: disable stack capture. + in: query + required: false + type: boolean + - name: trace_config.disable_storage + description: disable storage capture. + in: query + required: false + type: boolean + - name: trace_config.debug + description: print output during capture end. + in: query + required: false + type: boolean + - name: trace_config.limit + description: maximum length of output, but zero means unlimited. + in: query + required: false + type: integer + format: int32 + - name: trace_config.overrides.homestead_block + description: Homestead switch block (nil no fork, 0 = already homestead). + in: query + required: false + type: string + - name: trace_config.overrides.dao_fork_block + description: TheDAO hard-fork switch block (nil no fork). + in: query + required: false + type: string + - name: trace_config.overrides.dao_fork_support + description: Whether the nodes supports or opposes the DAO hard-fork. + in: query + required: false + type: boolean + - name: trace_config.overrides.eip150_block + description: >- + EIP150 implements the Gas price changes + + (https://github.com/ethereum/EIPs/issues/150) EIP150 HF block (nil + no fork). + in: query + required: false + type: string + - name: trace_config.overrides.eip150_hash + description: >- + EIP150 HF hash (needed for header only clients as only gas pricing + changed). + in: query + required: false + type: string + - name: trace_config.overrides.eip155_block + description: EIP155Block HF block. + in: query + required: false + type: string + - name: trace_config.overrides.eip158_block + description: EIP158 HF block. + in: query + required: false + type: string + - name: trace_config.overrides.byzantium_block + description: Byzantium switch block (nil no fork, 0 = already on byzantium). + in: query + required: false + type: string + - name: trace_config.overrides.constantinople_block + description: Constantinople switch block (nil no fork, 0 = already activated). + in: query + required: false + type: string + - name: trace_config.overrides.petersburg_block + description: Petersburg switch block (nil same as Constantinople). + in: query + required: false + type: string + - name: trace_config.overrides.istanbul_block + description: Istanbul switch block (nil no fork, 0 = already on istanbul). + in: query + required: false + type: string + - name: trace_config.overrides.muir_glacier_block + description: >- + Eip-2384 (bomb delay) switch block (nil no fork, 0 = already + activated). + in: query + required: false + type: string + - name: trace_config.overrides.berlin_block + description: Berlin switch block (nil = no fork, 0 = already on berlin). + in: query + required: false + type: string + - name: trace_config.overrides.london_block + description: London switch block (nil = no fork, 0 = already on london). + in: query + required: false + type: string + - name: trace_config.overrides.arrow_glacier_block + description: >- + Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already + activated). + in: query + required: false + type: string + - name: trace_config.overrides.gray_glacier_block + description: >- + EIP-5133 (bomb delay) switch block (nil = no fork, 0 = already + activated). + in: query + required: false + type: string + - name: trace_config.overrides.merge_netsplit_block + description: Virtual fork after The Merge to use as a network splitter. + in: query + required: false + type: string + - name: trace_config.enable_memory + description: enable memory capture. + in: query + required: false + type: boolean + - name: trace_config.enable_return_data + description: enable return data capture. + in: query + required: false + type: boolean + - name: trace_config.tracer_json_config + description: tracer config. + in: query + required: false + type: string + - name: block_number + description: block number of requested transaction. + in: query + required: false + type: string + format: int64 + - name: block_hash + description: block hex hash of requested transaction. + in: query + required: false + type: string + - name: block_time + description: block time of requested transaction. + in: query + required: false + type: string + format: date-time + - name: proposer_address + description: the proposer of the requested block. + in: query + required: false + type: string + format: byte + - name: chain_id + description: the eip155 chain id parsed from the requested block header. + in: query + required: false + type: string + format: int64 + tags: + - Ethermint + /ethermint/evm/v1/validator_account/{cons_address}: + get: + summary: >- + ValidatorAccount queries an Ethereum account's from a validator + consensus + + Address. + operationId: EthermintValidatorAccount + responses: + '200': + description: A successful response. + schema: + type: object + properties: + account_address: + type: string + description: >- + account_address is the cosmos address of the account in bech32 + format. + sequence: + type: string + format: uint64 + description: sequence is the account's sequence number. + account_number: + type: string + format: uint64 + title: account_number is the account number + description: |- + QueryValidatorAccountResponse is the response type for the + Query/ValidatorAccount RPC method. + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of + the serialized + + protocol buffer message. This string must contain at + least + + one "/" character. The last segment of the URL's path + must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in + a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary + all types that they + + expect it to use in the context of Any. However, for + URLs which use the + + scheme `http`, `https`, or no scheme, one can optionally + set up a type + + server that maps type URLs to message definitions as + follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based + on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in + the official + + protobuf release, and it is not used for type URLs + beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) + might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer + message along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values + in the form + + of utility functions or additional generated methods of the + Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := anypb.New(foo) + if err != nil { + ... + } + ... + foo := &pb.Foo{} + if err := any.UnmarshalTo(foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by + default use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the + last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield + type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with + an + + additional field `@type` which contains the type URL. + Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom + JSON + + representation, that representation will be embedded adding + a field + + `value` which holds the custom JSON in addition to the + `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + parameters: + - name: cons_address + description: cons_address is the validator cons address to query the account for. + in: path + required: true + type: string + tags: + - Ethermint /vesting/circulatingsupply: get: deprecated: true @@ -58787,6 +62239,56 @@ definitions: description: >- TotalSupplyResponse defines the response type for the Query/TotalSupply method. + kava.precisebank.v1.QueryFractionalBalanceResponse: + type: object + properties: + fractional_balance: + description: fractional_balance is the fractional balance of the address. + type: object + properties: + denom: + type: string + amount: + type: string + description: >- + QueryFractionalBalanceResponse defines the response type for + Query/FractionalBalance method. + kava.precisebank.v1.QueryRemainderResponse: + type: object + properties: + remainder: + description: >- + remainder is the amount backed by the reserve, but not yet owned by + any + + account, i.e. not in circulation. + type: object + properties: + denom: + type: string + amount: + type: string + description: >- + QueryRemainderResponse defines the response type for Query/Remainder + method. + kava.precisebank.v1.QueryTotalFractionalBalancesResponse: + type: object + properties: + total: + description: >- + total is the total sum of all fractional balances managed by the + precisebank + + module. + type: object + properties: + denom: + type: string + amount: + type: string + description: >- + QueryTotalFractionalBalancesResponse defines the response type for + Query/TotalFractionalBalances method. kava.pricefeed.v1beta1.CurrentPriceResponse: type: object properties: @@ -89548,6 +93050,827 @@ definitions: ready to send and receive packets. - STATE_CLOSED: A channel has been closed and can no longer be used to send or receive packets. + ethermint.evm.v1.ChainConfig: + type: object + properties: + homestead_block: + type: string + title: Homestead switch block (nil no fork, 0 = already homestead) + dao_fork_block: + type: string + title: TheDAO hard-fork switch block (nil no fork) + dao_fork_support: + type: boolean + title: Whether the nodes supports or opposes the DAO hard-fork + eip150_block: + type: string + title: >- + EIP150 implements the Gas price changes + + (https://github.com/ethereum/EIPs/issues/150) EIP150 HF block (nil no + fork) + eip150_hash: + type: string + title: >- + EIP150 HF hash (needed for header only clients as only gas pricing + changed) + eip155_block: + type: string + title: EIP155Block HF block + eip158_block: + type: string + title: EIP158 HF block + byzantium_block: + type: string + title: Byzantium switch block (nil no fork, 0 = already on byzantium) + constantinople_block: + type: string + title: Constantinople switch block (nil no fork, 0 = already activated) + petersburg_block: + type: string + title: Petersburg switch block (nil same as Constantinople) + istanbul_block: + type: string + title: Istanbul switch block (nil no fork, 0 = already on istanbul) + muir_glacier_block: + type: string + title: >- + Eip-2384 (bomb delay) switch block (nil no fork, 0 = already + activated) + berlin_block: + type: string + title: Berlin switch block (nil = no fork, 0 = already on berlin) + london_block: + type: string + title: London switch block (nil = no fork, 0 = already on london) + arrow_glacier_block: + type: string + title: >- + Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already + activated) + gray_glacier_block: + type: string + title: >- + EIP-5133 (bomb delay) switch block (nil = no fork, 0 = already + activated) + merge_netsplit_block: + type: string + title: Virtual fork after The Merge to use as a network splitter + description: >- + ChainConfig defines the Ethereum ChainConfig parameters using *sdk.Int + values + + instead of *big.Int. + ethermint.evm.v1.EstimateGasResponse: + type: object + properties: + gas: + type: string + format: uint64 + title: the estimated gas + title: EstimateGasResponse defines EstimateGas response + ethermint.evm.v1.Log: + type: object + properties: + address: + type: string + title: address of the contract that generated the event + topics: + type: array + items: + type: string + description: list of topics provided by the contract. + data: + type: string + format: byte + title: supplied by the contract, usually ABI-encoded + block_number: + type: string + format: uint64 + title: block in which the transaction was included + tx_hash: + type: string + title: hash of the transaction + tx_index: + type: string + format: uint64 + title: index of the transaction in the block + block_hash: + type: string + title: hash of the block in which the transaction was included + index: + type: string + format: uint64 + title: index of the log in the block + removed: + type: boolean + description: >- + The Removed field is true if this log was reverted due to a chain + + reorganisation. You must pay attention to this field if you receive + logs + + through a filter query. + description: >- + Log represents an protobuf compatible Ethereum Log that defines a contract + + log event. These events are generated by the LOG opcode and stored/indexed + by + + the node. + ethermint.evm.v1.MsgEthereumTx: + type: object + properties: + data: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of the + serialized + + protocol buffer message. This string must contain at least + + one "/" character. The last segment of the URL's path must + represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in a + canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary all types + that they + + expect it to use in the context of Any. However, for URLs which + use the + + scheme `http`, `https`, or no scheme, one can optionally set up a + type + + server that maps type URLs to message definitions as follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in the + official + + protobuf release, and it is not used for type URLs beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above specified + type. + description: >- + `Any` contains an arbitrary serialized protocol buffer message along + with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values in the + form + + of utility functions or additional generated methods of the Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := anypb.New(foo) + if err != nil { + ... + } + ... + foo := &pb.Foo{} + if err := any.UnmarshalTo(foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by default use + + 'type.googleapis.com/full.type.name' as the type URL and the unpack + + methods only use the fully qualified type name after the last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with an + + additional field `@type` which contains the type URL. Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom JSON + + representation, that representation will be embedded adding a field + + `value` which holds the custom JSON in addition to the `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + title: inner transaction data + size: + type: number + format: double + title: 'DEPRECATED: encoded storage size of the transaction' + hash: + type: string + title: transaction hash in hex format + from: + type: string + title: |- + ethereum signer address in hex format. This address value is checked + against the address derived from the signature (V, R, S) using the + secp256k1 elliptic curve + description: MsgEthereumTx encapsulates an Ethereum transaction as an SDK message. + ethermint.evm.v1.MsgEthereumTxResponse: + type: object + properties: + hash: + type: string + title: |- + ethereum transaction hash in hex format. This hash differs from the + Tendermint sha256 hash of the transaction bytes. See + https://github.com/tendermint/tendermint/issues/6539 for reference + logs: + type: array + items: + type: object + properties: + address: + type: string + title: address of the contract that generated the event + topics: + type: array + items: + type: string + description: list of topics provided by the contract. + data: + type: string + format: byte + title: supplied by the contract, usually ABI-encoded + block_number: + type: string + format: uint64 + title: block in which the transaction was included + tx_hash: + type: string + title: hash of the transaction + tx_index: + type: string + format: uint64 + title: index of the transaction in the block + block_hash: + type: string + title: hash of the block in which the transaction was included + index: + type: string + format: uint64 + title: index of the log in the block + removed: + type: boolean + description: >- + The Removed field is true if this log was reverted due to a + chain + + reorganisation. You must pay attention to this field if you + receive logs + + through a filter query. + description: >- + Log represents an protobuf compatible Ethereum Log that defines a + contract + + log event. These events are generated by the LOG opcode and + stored/indexed by + + the node. + description: |- + logs contains the transaction hash and the proto-compatible ethereum + logs. + ret: + type: string + format: byte + title: |- + returned data from evm function (result or data supplied with revert + opcode) + vm_error: + type: string + title: vm error is the error returned by vm execution + gas_used: + type: string + format: uint64 + title: gas consumed by the transaction + description: MsgEthereumTxResponse defines the Msg/EthereumTx response type. + ethermint.evm.v1.Params: + type: object + properties: + evm_denom: + type: string + description: |- + evm denom represents the token denomination used to run the EVM state + transitions. + enable_create: + type: boolean + title: >- + enable create toggles state transitions that use the vm.Create + function + enable_call: + type: boolean + title: enable call toggles state transitions that use the vm.Call function + extra_eips: + type: array + items: + type: string + format: int64 + title: extra eips defines the additional EIPs for the vm.Config + chain_config: + title: chain config defines the EVM chain configuration parameters + type: object + properties: + homestead_block: + type: string + title: Homestead switch block (nil no fork, 0 = already homestead) + dao_fork_block: + type: string + title: TheDAO hard-fork switch block (nil no fork) + dao_fork_support: + type: boolean + title: Whether the nodes supports or opposes the DAO hard-fork + eip150_block: + type: string + title: >- + EIP150 implements the Gas price changes + + (https://github.com/ethereum/EIPs/issues/150) EIP150 HF block (nil + no fork) + eip150_hash: + type: string + title: >- + EIP150 HF hash (needed for header only clients as only gas pricing + changed) + eip155_block: + type: string + title: EIP155Block HF block + eip158_block: + type: string + title: EIP158 HF block + byzantium_block: + type: string + title: Byzantium switch block (nil no fork, 0 = already on byzantium) + constantinople_block: + type: string + title: Constantinople switch block (nil no fork, 0 = already activated) + petersburg_block: + type: string + title: Petersburg switch block (nil same as Constantinople) + istanbul_block: + type: string + title: Istanbul switch block (nil no fork, 0 = already on istanbul) + muir_glacier_block: + type: string + title: >- + Eip-2384 (bomb delay) switch block (nil no fork, 0 = already + activated) + berlin_block: + type: string + title: Berlin switch block (nil = no fork, 0 = already on berlin) + london_block: + type: string + title: London switch block (nil = no fork, 0 = already on london) + arrow_glacier_block: + type: string + title: >- + Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already + activated) + gray_glacier_block: + type: string + title: >- + EIP-5133 (bomb delay) switch block (nil = no fork, 0 = already + activated) + merge_netsplit_block: + type: string + title: Virtual fork after The Merge to use as a network splitter + description: >- + ChainConfig defines the Ethereum ChainConfig parameters using *sdk.Int + values + + instead of *big.Int. + allow_unprotected_txs: + type: boolean + description: >- + Allow unprotected transactions defines if replay-protected (i.e non + EIP155 + + signed) transactions can be executed on the state machine. + title: Params defines the EVM module parameters + ethermint.evm.v1.QueryAccountResponse: + type: object + properties: + balance: + type: string + description: balance is the balance of the EVM denomination. + code_hash: + type: string + description: code hash is the hex-formatted code bytes from the EOA. + nonce: + type: string + format: uint64 + description: nonce is the account's sequence number. + description: >- + QueryAccountResponse is the response type for the Query/Account RPC + method. + ethermint.evm.v1.QueryBalanceResponse: + type: object + properties: + balance: + type: string + description: balance is the balance of the EVM denomination. + description: >- + QueryBalanceResponse is the response type for the Query/Balance RPC + method. + ethermint.evm.v1.QueryBaseFeeResponse: + type: object + properties: + base_fee: + type: string + description: BaseFeeResponse returns the EIP1559 base fee. + ethermint.evm.v1.QueryCodeResponse: + type: object + properties: + code: + type: string + format: byte + description: code represents the code bytes from an ethereum address. + description: |- + QueryCodeResponse is the response type for the Query/Code RPC + method. + ethermint.evm.v1.QueryCosmosAccountResponse: + type: object + properties: + cosmos_address: + type: string + description: cosmos_address is the cosmos address of the account. + sequence: + type: string + format: uint64 + description: sequence is the account's sequence number. + account_number: + type: string + format: uint64 + title: account_number is the account numbert + description: >- + QueryCosmosAccountResponse is the response type for the + Query/CosmosAccount + + RPC method. + ethermint.evm.v1.QueryParamsResponse: + type: object + properties: + params: + description: params define the evm module parameters. + type: object + properties: + evm_denom: + type: string + description: >- + evm denom represents the token denomination used to run the EVM + state + + transitions. + enable_create: + type: boolean + title: >- + enable create toggles state transitions that use the vm.Create + function + enable_call: + type: boolean + title: >- + enable call toggles state transitions that use the vm.Call + function + extra_eips: + type: array + items: + type: string + format: int64 + title: extra eips defines the additional EIPs for the vm.Config + chain_config: + title: chain config defines the EVM chain configuration parameters + type: object + properties: + homestead_block: + type: string + title: Homestead switch block (nil no fork, 0 = already homestead) + dao_fork_block: + type: string + title: TheDAO hard-fork switch block (nil no fork) + dao_fork_support: + type: boolean + title: Whether the nodes supports or opposes the DAO hard-fork + eip150_block: + type: string + title: >- + EIP150 implements the Gas price changes + + (https://github.com/ethereum/EIPs/issues/150) EIP150 HF block + (nil no fork) + eip150_hash: + type: string + title: >- + EIP150 HF hash (needed for header only clients as only gas + pricing changed) + eip155_block: + type: string + title: EIP155Block HF block + eip158_block: + type: string + title: EIP158 HF block + byzantium_block: + type: string + title: Byzantium switch block (nil no fork, 0 = already on byzantium) + constantinople_block: + type: string + title: >- + Constantinople switch block (nil no fork, 0 = already + activated) + petersburg_block: + type: string + title: Petersburg switch block (nil same as Constantinople) + istanbul_block: + type: string + title: Istanbul switch block (nil no fork, 0 = already on istanbul) + muir_glacier_block: + type: string + title: >- + Eip-2384 (bomb delay) switch block (nil no fork, 0 = already + activated) + berlin_block: + type: string + title: Berlin switch block (nil = no fork, 0 = already on berlin) + london_block: + type: string + title: London switch block (nil = no fork, 0 = already on london) + arrow_glacier_block: + type: string + title: >- + Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already + activated) + gray_glacier_block: + type: string + title: >- + EIP-5133 (bomb delay) switch block (nil = no fork, 0 = already + activated) + merge_netsplit_block: + type: string + title: Virtual fork after The Merge to use as a network splitter + description: >- + ChainConfig defines the Ethereum ChainConfig parameters using + *sdk.Int values + + instead of *big.Int. + allow_unprotected_txs: + type: boolean + description: >- + Allow unprotected transactions defines if replay-protected (i.e + non EIP155 + + signed) transactions can be executed on the state machine. + title: Params defines the EVM module parameters + description: >- + QueryParamsResponse defines the response type for querying x/evm + parameters. + ethermint.evm.v1.QueryStorageResponse: + type: object + properties: + value: + type: string + description: >- + key defines the storage state value hash associated with the given + key. + description: |- + QueryStorageResponse is the response type for the Query/Storage RPC + method. + ethermint.evm.v1.QueryTraceBlockResponse: + type: object + properties: + data: + type: string + format: byte + title: QueryTraceBlockResponse defines TraceBlock response + ethermint.evm.v1.QueryTraceTxResponse: + type: object + properties: + data: + type: string + format: byte + title: response serialized in bytes + title: QueryTraceTxResponse defines TraceTx response + ethermint.evm.v1.QueryValidatorAccountResponse: + type: object + properties: + account_address: + type: string + description: account_address is the cosmos address of the account in bech32 format. + sequence: + type: string + format: uint64 + description: sequence is the account's sequence number. + account_number: + type: string + format: uint64 + title: account_number is the account number + description: |- + QueryValidatorAccountResponse is the response type for the + Query/ValidatorAccount RPC method. + ethermint.evm.v1.TraceConfig: + type: object + properties: + tracer: + type: string + title: custom javascript tracer + timeout: + type: string + title: >- + overrides the default timeout of 5 seconds for JavaScript-based + tracing + + calls + reexec: + type: string + format: uint64 + title: number of blocks the tracer is willing to go back + disable_stack: + type: boolean + title: disable stack capture + disable_storage: + type: boolean + title: disable storage capture + debug: + type: boolean + title: print output during capture end + limit: + type: integer + format: int32 + title: maximum length of output, but zero means unlimited + overrides: + title: >- + Chain overrides, can be used to execute a trace using future fork + rules + type: object + properties: + homestead_block: + type: string + title: Homestead switch block (nil no fork, 0 = already homestead) + dao_fork_block: + type: string + title: TheDAO hard-fork switch block (nil no fork) + dao_fork_support: + type: boolean + title: Whether the nodes supports or opposes the DAO hard-fork + eip150_block: + type: string + title: >- + EIP150 implements the Gas price changes + + (https://github.com/ethereum/EIPs/issues/150) EIP150 HF block (nil + no fork) + eip150_hash: + type: string + title: >- + EIP150 HF hash (needed for header only clients as only gas pricing + changed) + eip155_block: + type: string + title: EIP155Block HF block + eip158_block: + type: string + title: EIP158 HF block + byzantium_block: + type: string + title: Byzantium switch block (nil no fork, 0 = already on byzantium) + constantinople_block: + type: string + title: Constantinople switch block (nil no fork, 0 = already activated) + petersburg_block: + type: string + title: Petersburg switch block (nil same as Constantinople) + istanbul_block: + type: string + title: Istanbul switch block (nil no fork, 0 = already on istanbul) + muir_glacier_block: + type: string + title: >- + Eip-2384 (bomb delay) switch block (nil no fork, 0 = already + activated) + berlin_block: + type: string + title: Berlin switch block (nil = no fork, 0 = already on berlin) + london_block: + type: string + title: London switch block (nil = no fork, 0 = already on london) + arrow_glacier_block: + type: string + title: >- + Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already + activated) + gray_glacier_block: + type: string + title: >- + EIP-5133 (bomb delay) switch block (nil = no fork, 0 = already + activated) + merge_netsplit_block: + type: string + title: Virtual fork after The Merge to use as a network splitter + description: >- + ChainConfig defines the Ethereum ChainConfig parameters using *sdk.Int + values + + instead of *big.Int. + enable_memory: + type: boolean + title: enable memory capture + enable_return_data: + type: boolean + title: enable return data capture + tracer_json_config: + type: string + title: tracer config + description: TraceConfig holds extra parameters to trace functions. securityDefinitions: kms: type: basic diff --git a/client/erc20/MintableBurnableERC20.abi b/client/erc20/MintableBurnableERC20.abi new file mode 100644 index 00000000..ec58ba28 --- /dev/null +++ b/client/erc20/MintableBurnableERC20.abi @@ -0,0 +1,381 @@ +[ + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] diff --git a/client/erc20/MintableBurnableERC20.bin b/client/erc20/MintableBurnableERC20.bin new file mode 100644 index 00000000..ace0ce62 --- /dev/null +++ b/client/erc20/MintableBurnableERC20.bin @@ -0,0 +1 @@ +60a06040523480156200001157600080fd5b506040516200114c3803806200114c83398101604081905262000034916200019a565b82826003620000448382620002ae565b506004620000538282620002ae565b505050620000706200006a6200007f60201b60201c565b62000083565b60ff16608052506200037a9050565b3390565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000fd57600080fd5b81516001600160401b03808211156200011a576200011a620000d5565b604051601f8301601f19908116603f01168101908282118183101715620001455762000145620000d5565b816040528381526020925086838588010111156200016257600080fd5b600091505b8382101562000186578582018301518183018401529082019062000167565b600093810190920192909252949350505050565b600080600060608486031215620001b057600080fd5b83516001600160401b0380821115620001c857600080fd5b620001d687838801620000eb565b94506020860151915080821115620001ed57600080fd5b50620001fc86828701620000eb565b925050604084015160ff811681146200021457600080fd5b809150509250925092565b600181811c908216806200023457607f821691505b6020821081036200025557634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620002a957600081815260208120601f850160051c81016020861015620002845750805b601f850160051c820191505b81811015620002a55782815560010162000290565b5050505b505050565b81516001600160401b03811115620002ca57620002ca620000d5565b620002e281620002db84546200021f565b846200025b565b602080601f8311600181146200031a5760008415620003015750858301515b600019600386901b1c1916600185901b178555620002a5565b600085815260208120601f198616915b828110156200034b578886015182559484019460019091019084016200032a565b50858210156200036a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b608051610db66200039660003960006101720152610db66000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c8063715018a611610097578063a457c2d711610066578063a457c2d71461022b578063a9059cbb1461023e578063dd62ed3e14610251578063f2fde38b1461028a57600080fd5b8063715018a6146101ed5780638da5cb5b146101f557806395d89b41146102105780639dc29fac1461021857600080fd5b8063313ce567116100d3578063313ce5671461016b578063395093511461019c57806340c10f19146101af57806370a08231146101c457600080fd5b806306fdde0314610105578063095ea7b31461012357806318160ddd1461014657806323b872dd14610158575b600080fd5b61010d61029d565b60405161011a9190610c00565b60405180910390f35b610136610131366004610c6a565b61032f565b604051901515815260200161011a565b6002545b60405190815260200161011a565b610136610166366004610c94565b610349565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161011a565b6101366101aa366004610c6a565b61036d565b6101c26101bd366004610c6a565b6103ac565b005b61014a6101d2366004610cd0565b6001600160a01b031660009081526020819052604090205490565b6101c26103c2565b6005546040516001600160a01b03909116815260200161011a565b61010d6103d6565b6101c2610226366004610c6a565b6103e5565b610136610239366004610c6a565b6103f7565b61013661024c366004610c6a565b6104a6565b61014a61025f366004610cf2565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6101c2610298366004610cd0565b6104b4565b6060600380546102ac90610d25565b80601f01602080910402602001604051908101604052809291908181526020018280546102d890610d25565b80156103255780601f106102fa57610100808354040283529160200191610325565b820191906000526020600020905b81548152906001019060200180831161030857829003601f168201915b5050505050905090565b60003361033d818585610544565b60019150505b92915050565b60003361035785828561069d565b61036285858561072f565b506001949350505050565b3360008181526001602090815260408083206001600160a01b038716845290915281205490919061033d90829086906103a7908790610d5f565b610544565b6103b461091c565b6103be8282610976565b5050565b6103ca61091c565b6103d46000610a35565b565b6060600480546102ac90610d25565b6103ed61091c565b6103be8282610a9f565b3360008181526001602090815260408083206001600160a01b0387168452909152812054909190838110156104995760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6103628286868403610544565b60003361033d81858561072f565b6104bc61091c565b6001600160a01b0381166105385760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610490565b61054181610a35565b50565b6001600160a01b0383166105bf5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610490565b6001600160a01b03821661063b5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610490565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6001600160a01b038381166000908152600160209081526040808320938616835292905220546000198114610729578181101561071c5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610490565b6107298484848403610544565b50505050565b6001600160a01b0383166107ab5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610490565b6001600160a01b0382166108275760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610490565b6001600160a01b038316600090815260208190526040902054818110156108b65760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610490565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610729565b6005546001600160a01b031633146103d45760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610490565b6001600160a01b0382166109cc5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610490565b80600260008282546109de9190610d5f565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b600580546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b038216610b1b5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610490565b6001600160a01b03821660009081526020819052604090205481811015610baa5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610490565b6001600160a01b0383166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610690565b600060208083528351808285015260005b81811015610c2d57858101830151858201604001528201610c11565b506000604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b0381168114610c6557600080fd5b919050565b60008060408385031215610c7d57600080fd5b610c8683610c4e565b946020939093013593505050565b600080600060608486031215610ca957600080fd5b610cb284610c4e565b9250610cc060208501610c4e565b9150604084013590509250925092565b600060208284031215610ce257600080fd5b610ceb82610c4e565b9392505050565b60008060408385031215610d0557600080fd5b610d0e83610c4e565b9150610d1c60208401610c4e565b90509250929050565b600181811c90821680610d3957607f821691505b602082108103610d5957634e487b7160e01b600052602260045260246000fd5b50919050565b8082018082111561034357634e487b7160e01b600052601160045260246000fdfea26469706673582212208fcfb0bbf7b13fa310f31ff223af3c08b9749eb7903e49018ed56401383786f964736f6c63430008120033 diff --git a/client/erc20/main.go b/client/erc20/main.go new file mode 100644 index 00000000..30e748e6 --- /dev/null +++ b/client/erc20/main.go @@ -0,0 +1,1069 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package erc20 + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription +) + +// Erc20MetaData contains all meta data concerning the Erc20 contract. +var Erc20MetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"decimals_\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60a06040523480156200001157600080fd5b506040516200114c3803806200114c83398101604081905262000034916200019a565b82826003620000448382620002ae565b506004620000538282620002ae565b505050620000706200006a6200007f60201b60201c565b62000083565b60ff16608052506200037a9050565b3390565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000fd57600080fd5b81516001600160401b03808211156200011a576200011a620000d5565b604051601f8301601f19908116603f01168101908282118183101715620001455762000145620000d5565b816040528381526020925086838588010111156200016257600080fd5b600091505b8382101562000186578582018301518183018401529082019062000167565b600093810190920192909252949350505050565b600080600060608486031215620001b057600080fd5b83516001600160401b0380821115620001c857600080fd5b620001d687838801620000eb565b94506020860151915080821115620001ed57600080fd5b50620001fc86828701620000eb565b925050604084015160ff811681146200021457600080fd5b809150509250925092565b600181811c908216806200023457607f821691505b6020821081036200025557634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620002a957600081815260208120601f850160051c81016020861015620002845750805b601f850160051c820191505b81811015620002a55782815560010162000290565b5050505b505050565b81516001600160401b03811115620002ca57620002ca620000d5565b620002e281620002db84546200021f565b846200025b565b602080601f8311600181146200031a5760008415620003015750858301515b600019600386901b1c1916600185901b178555620002a5565b600085815260208120601f198616915b828110156200034b578886015182559484019460019091019084016200032a565b50858210156200036a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b608051610db66200039660003960006101720152610db66000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c8063715018a611610097578063a457c2d711610066578063a457c2d71461022b578063a9059cbb1461023e578063dd62ed3e14610251578063f2fde38b1461028a57600080fd5b8063715018a6146101ed5780638da5cb5b146101f557806395d89b41146102105780639dc29fac1461021857600080fd5b8063313ce567116100d3578063313ce5671461016b578063395093511461019c57806340c10f19146101af57806370a08231146101c457600080fd5b806306fdde0314610105578063095ea7b31461012357806318160ddd1461014657806323b872dd14610158575b600080fd5b61010d61029d565b60405161011a9190610c00565b60405180910390f35b610136610131366004610c6a565b61032f565b604051901515815260200161011a565b6002545b60405190815260200161011a565b610136610166366004610c94565b610349565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161011a565b6101366101aa366004610c6a565b61036d565b6101c26101bd366004610c6a565b6103ac565b005b61014a6101d2366004610cd0565b6001600160a01b031660009081526020819052604090205490565b6101c26103c2565b6005546040516001600160a01b03909116815260200161011a565b61010d6103d6565b6101c2610226366004610c6a565b6103e5565b610136610239366004610c6a565b6103f7565b61013661024c366004610c6a565b6104a6565b61014a61025f366004610cf2565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6101c2610298366004610cd0565b6104b4565b6060600380546102ac90610d25565b80601f01602080910402602001604051908101604052809291908181526020018280546102d890610d25565b80156103255780601f106102fa57610100808354040283529160200191610325565b820191906000526020600020905b81548152906001019060200180831161030857829003601f168201915b5050505050905090565b60003361033d818585610544565b60019150505b92915050565b60003361035785828561069d565b61036285858561072f565b506001949350505050565b3360008181526001602090815260408083206001600160a01b038716845290915281205490919061033d90829086906103a7908790610d5f565b610544565b6103b461091c565b6103be8282610976565b5050565b6103ca61091c565b6103d46000610a35565b565b6060600480546102ac90610d25565b6103ed61091c565b6103be8282610a9f565b3360008181526001602090815260408083206001600160a01b0387168452909152812054909190838110156104995760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6103628286868403610544565b60003361033d81858561072f565b6104bc61091c565b6001600160a01b0381166105385760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610490565b61054181610a35565b50565b6001600160a01b0383166105bf5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610490565b6001600160a01b03821661063b5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610490565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6001600160a01b038381166000908152600160209081526040808320938616835292905220546000198114610729578181101561071c5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610490565b6107298484848403610544565b50505050565b6001600160a01b0383166107ab5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610490565b6001600160a01b0382166108275760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610490565b6001600160a01b038316600090815260208190526040902054818110156108b65760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610490565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610729565b6005546001600160a01b031633146103d45760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610490565b6001600160a01b0382166109cc5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610490565b80600260008282546109de9190610d5f565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b600580546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b038216610b1b5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610490565b6001600160a01b03821660009081526020819052604090205481811015610baa5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610490565b6001600160a01b0383166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610690565b600060208083528351808285015260005b81811015610c2d57858101830151858201604001528201610c11565b506000604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b0381168114610c6557600080fd5b919050565b60008060408385031215610c7d57600080fd5b610c8683610c4e565b946020939093013593505050565b600080600060608486031215610ca957600080fd5b610cb284610c4e565b9250610cc060208501610c4e565b9150604084013590509250925092565b600060208284031215610ce257600080fd5b610ceb82610c4e565b9392505050565b60008060408385031215610d0557600080fd5b610d0e83610c4e565b9150610d1c60208401610c4e565b90509250929050565b600181811c90821680610d3957607f821691505b602082108103610d5957634e487b7160e01b600052602260045260246000fd5b50919050565b8082018082111561034357634e487b7160e01b600052601160045260246000fdfea26469706673582212208fcfb0bbf7b13fa310f31ff223af3c08b9749eb7903e49018ed56401383786f964736f6c63430008120033", +} + +// Erc20ABI is the input ABI used to generate the binding from. +// Deprecated: Use Erc20MetaData.ABI instead. +var Erc20ABI = Erc20MetaData.ABI + +// Erc20Bin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use Erc20MetaData.Bin instead. +var Erc20Bin = Erc20MetaData.Bin + +// DeployErc20 deploys a new Ethereum contract, binding an instance of Erc20 to it. +func DeployErc20(auth *bind.TransactOpts, backend bind.ContractBackend, name string, symbol string, decimals_ uint8) (common.Address, *types.Transaction, *Erc20, error) { + parsed, err := Erc20MetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(Erc20Bin), backend, name, symbol, decimals_) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Erc20{Erc20Caller: Erc20Caller{contract: contract}, Erc20Transactor: Erc20Transactor{contract: contract}, Erc20Filterer: Erc20Filterer{contract: contract}}, nil +} + +// Erc20 is an auto generated Go binding around an Ethereum contract. +type Erc20 struct { + Erc20Caller // Read-only binding to the contract + Erc20Transactor // Write-only binding to the contract + Erc20Filterer // Log filterer for contract events +} + +// Erc20Caller is an auto generated read-only Go binding around an Ethereum contract. +type Erc20Caller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Erc20Transactor is an auto generated write-only Go binding around an Ethereum contract. +type Erc20Transactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Erc20Filterer is an auto generated log filtering Go binding around an Ethereum contract events. +type Erc20Filterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Erc20Session is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type Erc20Session struct { + Contract *Erc20 // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// Erc20CallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type Erc20CallerSession struct { + Contract *Erc20Caller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// Erc20TransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type Erc20TransactorSession struct { + Contract *Erc20Transactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// Erc20Raw is an auto generated low-level Go binding around an Ethereum contract. +type Erc20Raw struct { + Contract *Erc20 // Generic contract binding to access the raw methods on +} + +// Erc20CallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type Erc20CallerRaw struct { + Contract *Erc20Caller // Generic read-only contract binding to access the raw methods on +} + +// Erc20TransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type Erc20TransactorRaw struct { + Contract *Erc20Transactor // Generic write-only contract binding to access the raw methods on +} + +// NewErc20 creates a new instance of Erc20, bound to a specific deployed contract. +func NewErc20(address common.Address, backend bind.ContractBackend) (*Erc20, error) { + contract, err := bindErc20(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Erc20{Erc20Caller: Erc20Caller{contract: contract}, Erc20Transactor: Erc20Transactor{contract: contract}, Erc20Filterer: Erc20Filterer{contract: contract}}, nil +} + +// NewErc20Caller creates a new read-only instance of Erc20, bound to a specific deployed contract. +func NewErc20Caller(address common.Address, caller bind.ContractCaller) (*Erc20Caller, error) { + contract, err := bindErc20(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &Erc20Caller{contract: contract}, nil +} + +// NewErc20Transactor creates a new write-only instance of Erc20, bound to a specific deployed contract. +func NewErc20Transactor(address common.Address, transactor bind.ContractTransactor) (*Erc20Transactor, error) { + contract, err := bindErc20(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &Erc20Transactor{contract: contract}, nil +} + +// NewErc20Filterer creates a new log filterer instance of Erc20, bound to a specific deployed contract. +func NewErc20Filterer(address common.Address, filterer bind.ContractFilterer) (*Erc20Filterer, error) { + contract, err := bindErc20(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &Erc20Filterer{contract: contract}, nil +} + +// bindErc20 binds a generic wrapper to an already deployed contract. +func bindErc20(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(Erc20ABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Erc20 *Erc20Raw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Erc20.Contract.Erc20Caller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Erc20 *Erc20Raw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Erc20.Contract.Erc20Transactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Erc20 *Erc20Raw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Erc20.Contract.Erc20Transactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Erc20 *Erc20CallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Erc20.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Erc20 *Erc20TransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Erc20.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Erc20 *Erc20TransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Erc20.Contract.contract.Transact(opts, method, params...) +} + +// Allowance is a free data retrieval call binding the contract method 0xdd62ed3e. +// +// Solidity: function allowance(address owner, address spender) view returns(uint256) +func (_Erc20 *Erc20Caller) Allowance(opts *bind.CallOpts, owner common.Address, spender common.Address) (*big.Int, error) { + var out []interface{} + err := _Erc20.contract.Call(opts, &out, "allowance", owner, spender) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// Allowance is a free data retrieval call binding the contract method 0xdd62ed3e. +// +// Solidity: function allowance(address owner, address spender) view returns(uint256) +func (_Erc20 *Erc20Session) Allowance(owner common.Address, spender common.Address) (*big.Int, error) { + return _Erc20.Contract.Allowance(&_Erc20.CallOpts, owner, spender) +} + +// Allowance is a free data retrieval call binding the contract method 0xdd62ed3e. +// +// Solidity: function allowance(address owner, address spender) view returns(uint256) +func (_Erc20 *Erc20CallerSession) Allowance(owner common.Address, spender common.Address) (*big.Int, error) { + return _Erc20.Contract.Allowance(&_Erc20.CallOpts, owner, spender) +} + +// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. +// +// Solidity: function balanceOf(address account) view returns(uint256) +func (_Erc20 *Erc20Caller) BalanceOf(opts *bind.CallOpts, account common.Address) (*big.Int, error) { + var out []interface{} + err := _Erc20.contract.Call(opts, &out, "balanceOf", account) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. +// +// Solidity: function balanceOf(address account) view returns(uint256) +func (_Erc20 *Erc20Session) BalanceOf(account common.Address) (*big.Int, error) { + return _Erc20.Contract.BalanceOf(&_Erc20.CallOpts, account) +} + +// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. +// +// Solidity: function balanceOf(address account) view returns(uint256) +func (_Erc20 *Erc20CallerSession) BalanceOf(account common.Address) (*big.Int, error) { + return _Erc20.Contract.BalanceOf(&_Erc20.CallOpts, account) +} + +// Decimals is a free data retrieval call binding the contract method 0x313ce567. +// +// Solidity: function decimals() view returns(uint8) +func (_Erc20 *Erc20Caller) Decimals(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _Erc20.contract.Call(opts, &out, "decimals") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +// Decimals is a free data retrieval call binding the contract method 0x313ce567. +// +// Solidity: function decimals() view returns(uint8) +func (_Erc20 *Erc20Session) Decimals() (uint8, error) { + return _Erc20.Contract.Decimals(&_Erc20.CallOpts) +} + +// Decimals is a free data retrieval call binding the contract method 0x313ce567. +// +// Solidity: function decimals() view returns(uint8) +func (_Erc20 *Erc20CallerSession) Decimals() (uint8, error) { + return _Erc20.Contract.Decimals(&_Erc20.CallOpts) +} + +// Name is a free data retrieval call binding the contract method 0x06fdde03. +// +// Solidity: function name() view returns(string) +func (_Erc20 *Erc20Caller) Name(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _Erc20.contract.Call(opts, &out, "name") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// Name is a free data retrieval call binding the contract method 0x06fdde03. +// +// Solidity: function name() view returns(string) +func (_Erc20 *Erc20Session) Name() (string, error) { + return _Erc20.Contract.Name(&_Erc20.CallOpts) +} + +// Name is a free data retrieval call binding the contract method 0x06fdde03. +// +// Solidity: function name() view returns(string) +func (_Erc20 *Erc20CallerSession) Name() (string, error) { + return _Erc20.Contract.Name(&_Erc20.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Erc20 *Erc20Caller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Erc20.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Erc20 *Erc20Session) Owner() (common.Address, error) { + return _Erc20.Contract.Owner(&_Erc20.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Erc20 *Erc20CallerSession) Owner() (common.Address, error) { + return _Erc20.Contract.Owner(&_Erc20.CallOpts) +} + +// Symbol is a free data retrieval call binding the contract method 0x95d89b41. +// +// Solidity: function symbol() view returns(string) +func (_Erc20 *Erc20Caller) Symbol(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _Erc20.contract.Call(opts, &out, "symbol") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// Symbol is a free data retrieval call binding the contract method 0x95d89b41. +// +// Solidity: function symbol() view returns(string) +func (_Erc20 *Erc20Session) Symbol() (string, error) { + return _Erc20.Contract.Symbol(&_Erc20.CallOpts) +} + +// Symbol is a free data retrieval call binding the contract method 0x95d89b41. +// +// Solidity: function symbol() view returns(string) +func (_Erc20 *Erc20CallerSession) Symbol() (string, error) { + return _Erc20.Contract.Symbol(&_Erc20.CallOpts) +} + +// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. +// +// Solidity: function totalSupply() view returns(uint256) +func (_Erc20 *Erc20Caller) TotalSupply(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Erc20.contract.Call(opts, &out, "totalSupply") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. +// +// Solidity: function totalSupply() view returns(uint256) +func (_Erc20 *Erc20Session) TotalSupply() (*big.Int, error) { + return _Erc20.Contract.TotalSupply(&_Erc20.CallOpts) +} + +// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. +// +// Solidity: function totalSupply() view returns(uint256) +func (_Erc20 *Erc20CallerSession) TotalSupply() (*big.Int, error) { + return _Erc20.Contract.TotalSupply(&_Erc20.CallOpts) +} + +// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. +// +// Solidity: function approve(address spender, uint256 amount) returns(bool) +func (_Erc20 *Erc20Transactor) Approve(opts *bind.TransactOpts, spender common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.contract.Transact(opts, "approve", spender, amount) +} + +// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. +// +// Solidity: function approve(address spender, uint256 amount) returns(bool) +func (_Erc20 *Erc20Session) Approve(spender common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.Contract.Approve(&_Erc20.TransactOpts, spender, amount) +} + +// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. +// +// Solidity: function approve(address spender, uint256 amount) returns(bool) +func (_Erc20 *Erc20TransactorSession) Approve(spender common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.Contract.Approve(&_Erc20.TransactOpts, spender, amount) +} + +// Burn is a paid mutator transaction binding the contract method 0x9dc29fac. +// +// Solidity: function burn(address from, uint256 amount) returns() +func (_Erc20 *Erc20Transactor) Burn(opts *bind.TransactOpts, from common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.contract.Transact(opts, "burn", from, amount) +} + +// Burn is a paid mutator transaction binding the contract method 0x9dc29fac. +// +// Solidity: function burn(address from, uint256 amount) returns() +func (_Erc20 *Erc20Session) Burn(from common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.Contract.Burn(&_Erc20.TransactOpts, from, amount) +} + +// Burn is a paid mutator transaction binding the contract method 0x9dc29fac. +// +// Solidity: function burn(address from, uint256 amount) returns() +func (_Erc20 *Erc20TransactorSession) Burn(from common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.Contract.Burn(&_Erc20.TransactOpts, from, amount) +} + +// DecreaseAllowance is a paid mutator transaction binding the contract method 0xa457c2d7. +// +// Solidity: function decreaseAllowance(address spender, uint256 subtractedValue) returns(bool) +func (_Erc20 *Erc20Transactor) DecreaseAllowance(opts *bind.TransactOpts, spender common.Address, subtractedValue *big.Int) (*types.Transaction, error) { + return _Erc20.contract.Transact(opts, "decreaseAllowance", spender, subtractedValue) +} + +// DecreaseAllowance is a paid mutator transaction binding the contract method 0xa457c2d7. +// +// Solidity: function decreaseAllowance(address spender, uint256 subtractedValue) returns(bool) +func (_Erc20 *Erc20Session) DecreaseAllowance(spender common.Address, subtractedValue *big.Int) (*types.Transaction, error) { + return _Erc20.Contract.DecreaseAllowance(&_Erc20.TransactOpts, spender, subtractedValue) +} + +// DecreaseAllowance is a paid mutator transaction binding the contract method 0xa457c2d7. +// +// Solidity: function decreaseAllowance(address spender, uint256 subtractedValue) returns(bool) +func (_Erc20 *Erc20TransactorSession) DecreaseAllowance(spender common.Address, subtractedValue *big.Int) (*types.Transaction, error) { + return _Erc20.Contract.DecreaseAllowance(&_Erc20.TransactOpts, spender, subtractedValue) +} + +// IncreaseAllowance is a paid mutator transaction binding the contract method 0x39509351. +// +// Solidity: function increaseAllowance(address spender, uint256 addedValue) returns(bool) +func (_Erc20 *Erc20Transactor) IncreaseAllowance(opts *bind.TransactOpts, spender common.Address, addedValue *big.Int) (*types.Transaction, error) { + return _Erc20.contract.Transact(opts, "increaseAllowance", spender, addedValue) +} + +// IncreaseAllowance is a paid mutator transaction binding the contract method 0x39509351. +// +// Solidity: function increaseAllowance(address spender, uint256 addedValue) returns(bool) +func (_Erc20 *Erc20Session) IncreaseAllowance(spender common.Address, addedValue *big.Int) (*types.Transaction, error) { + return _Erc20.Contract.IncreaseAllowance(&_Erc20.TransactOpts, spender, addedValue) +} + +// IncreaseAllowance is a paid mutator transaction binding the contract method 0x39509351. +// +// Solidity: function increaseAllowance(address spender, uint256 addedValue) returns(bool) +func (_Erc20 *Erc20TransactorSession) IncreaseAllowance(spender common.Address, addedValue *big.Int) (*types.Transaction, error) { + return _Erc20.Contract.IncreaseAllowance(&_Erc20.TransactOpts, spender, addedValue) +} + +// Mint is a paid mutator transaction binding the contract method 0x40c10f19. +// +// Solidity: function mint(address to, uint256 amount) returns() +func (_Erc20 *Erc20Transactor) Mint(opts *bind.TransactOpts, to common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.contract.Transact(opts, "mint", to, amount) +} + +// Mint is a paid mutator transaction binding the contract method 0x40c10f19. +// +// Solidity: function mint(address to, uint256 amount) returns() +func (_Erc20 *Erc20Session) Mint(to common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.Contract.Mint(&_Erc20.TransactOpts, to, amount) +} + +// Mint is a paid mutator transaction binding the contract method 0x40c10f19. +// +// Solidity: function mint(address to, uint256 amount) returns() +func (_Erc20 *Erc20TransactorSession) Mint(to common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.Contract.Mint(&_Erc20.TransactOpts, to, amount) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_Erc20 *Erc20Transactor) RenounceOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Erc20.contract.Transact(opts, "renounceOwnership") +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_Erc20 *Erc20Session) RenounceOwnership() (*types.Transaction, error) { + return _Erc20.Contract.RenounceOwnership(&_Erc20.TransactOpts) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_Erc20 *Erc20TransactorSession) RenounceOwnership() (*types.Transaction, error) { + return _Erc20.Contract.RenounceOwnership(&_Erc20.TransactOpts) +} + +// Transfer is a paid mutator transaction binding the contract method 0xa9059cbb. +// +// Solidity: function transfer(address to, uint256 amount) returns(bool) +func (_Erc20 *Erc20Transactor) Transfer(opts *bind.TransactOpts, to common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.contract.Transact(opts, "transfer", to, amount) +} + +// Transfer is a paid mutator transaction binding the contract method 0xa9059cbb. +// +// Solidity: function transfer(address to, uint256 amount) returns(bool) +func (_Erc20 *Erc20Session) Transfer(to common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.Contract.Transfer(&_Erc20.TransactOpts, to, amount) +} + +// Transfer is a paid mutator transaction binding the contract method 0xa9059cbb. +// +// Solidity: function transfer(address to, uint256 amount) returns(bool) +func (_Erc20 *Erc20TransactorSession) Transfer(to common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.Contract.Transfer(&_Erc20.TransactOpts, to, amount) +} + +// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. +// +// Solidity: function transferFrom(address from, address to, uint256 amount) returns(bool) +func (_Erc20 *Erc20Transactor) TransferFrom(opts *bind.TransactOpts, from common.Address, to common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.contract.Transact(opts, "transferFrom", from, to, amount) +} + +// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. +// +// Solidity: function transferFrom(address from, address to, uint256 amount) returns(bool) +func (_Erc20 *Erc20Session) TransferFrom(from common.Address, to common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.Contract.TransferFrom(&_Erc20.TransactOpts, from, to, amount) +} + +// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. +// +// Solidity: function transferFrom(address from, address to, uint256 amount) returns(bool) +func (_Erc20 *Erc20TransactorSession) TransferFrom(from common.Address, to common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.Contract.TransferFrom(&_Erc20.TransactOpts, from, to, amount) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Erc20 *Erc20Transactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { + return _Erc20.contract.Transact(opts, "transferOwnership", newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Erc20 *Erc20Session) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _Erc20.Contract.TransferOwnership(&_Erc20.TransactOpts, newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Erc20 *Erc20TransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _Erc20.Contract.TransferOwnership(&_Erc20.TransactOpts, newOwner) +} + +// Erc20ApprovalIterator is returned from FilterApproval and is used to iterate over the raw logs and unpacked data for Approval events raised by the Erc20 contract. +type Erc20ApprovalIterator struct { + Event *Erc20Approval // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *Erc20ApprovalIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(Erc20Approval) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(Erc20Approval) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *Erc20ApprovalIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *Erc20ApprovalIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// Erc20Approval represents a Approval event raised by the Erc20 contract. +type Erc20Approval struct { + Owner common.Address + Spender common.Address + Value *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterApproval is a free log retrieval operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. +// +// Solidity: event Approval(address indexed owner, address indexed spender, uint256 value) +func (_Erc20 *Erc20Filterer) FilterApproval(opts *bind.FilterOpts, owner []common.Address, spender []common.Address) (*Erc20ApprovalIterator, error) { + + var ownerRule []interface{} + for _, ownerItem := range owner { + ownerRule = append(ownerRule, ownerItem) + } + var spenderRule []interface{} + for _, spenderItem := range spender { + spenderRule = append(spenderRule, spenderItem) + } + + logs, sub, err := _Erc20.contract.FilterLogs(opts, "Approval", ownerRule, spenderRule) + if err != nil { + return nil, err + } + return &Erc20ApprovalIterator{contract: _Erc20.contract, event: "Approval", logs: logs, sub: sub}, nil +} + +// WatchApproval is a free log subscription operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. +// +// Solidity: event Approval(address indexed owner, address indexed spender, uint256 value) +func (_Erc20 *Erc20Filterer) WatchApproval(opts *bind.WatchOpts, sink chan<- *Erc20Approval, owner []common.Address, spender []common.Address) (event.Subscription, error) { + + var ownerRule []interface{} + for _, ownerItem := range owner { + ownerRule = append(ownerRule, ownerItem) + } + var spenderRule []interface{} + for _, spenderItem := range spender { + spenderRule = append(spenderRule, spenderItem) + } + + logs, sub, err := _Erc20.contract.WatchLogs(opts, "Approval", ownerRule, spenderRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(Erc20Approval) + if err := _Erc20.contract.UnpackLog(event, "Approval", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseApproval is a log parse operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. +// +// Solidity: event Approval(address indexed owner, address indexed spender, uint256 value) +func (_Erc20 *Erc20Filterer) ParseApproval(log types.Log) (*Erc20Approval, error) { + event := new(Erc20Approval) + if err := _Erc20.contract.UnpackLog(event, "Approval", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// Erc20OwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the Erc20 contract. +type Erc20OwnershipTransferredIterator struct { + Event *Erc20OwnershipTransferred // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *Erc20OwnershipTransferredIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(Erc20OwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(Erc20OwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *Erc20OwnershipTransferredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *Erc20OwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// Erc20OwnershipTransferred represents a OwnershipTransferred event raised by the Erc20 contract. +type Erc20OwnershipTransferred struct { + PreviousOwner common.Address + NewOwner common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterOwnershipTransferred is a free log retrieval operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_Erc20 *Erc20Filterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*Erc20OwnershipTransferredIterator, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _Erc20.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return &Erc20OwnershipTransferredIterator{contract: _Erc20.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +// WatchOwnershipTransferred is a free log subscription operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_Erc20 *Erc20Filterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *Erc20OwnershipTransferred, previousOwner []common.Address, newOwner []common.Address) (event.Subscription, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _Erc20.contract.WatchLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(Erc20OwnershipTransferred) + if err := _Erc20.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseOwnershipTransferred is a log parse operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_Erc20 *Erc20Filterer) ParseOwnershipTransferred(log types.Log) (*Erc20OwnershipTransferred, error) { + event := new(Erc20OwnershipTransferred) + if err := _Erc20.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// Erc20TransferIterator is returned from FilterTransfer and is used to iterate over the raw logs and unpacked data for Transfer events raised by the Erc20 contract. +type Erc20TransferIterator struct { + Event *Erc20Transfer // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *Erc20TransferIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(Erc20Transfer) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(Erc20Transfer) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *Erc20TransferIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *Erc20TransferIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// Erc20Transfer represents a Transfer event raised by the Erc20 contract. +type Erc20Transfer struct { + From common.Address + To common.Address + Value *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterTransfer is a free log retrieval operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. +// +// Solidity: event Transfer(address indexed from, address indexed to, uint256 value) +func (_Erc20 *Erc20Filterer) FilterTransfer(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*Erc20TransferIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _Erc20.contract.FilterLogs(opts, "Transfer", fromRule, toRule) + if err != nil { + return nil, err + } + return &Erc20TransferIterator{contract: _Erc20.contract, event: "Transfer", logs: logs, sub: sub}, nil +} + +// WatchTransfer is a free log subscription operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. +// +// Solidity: event Transfer(address indexed from, address indexed to, uint256 value) +func (_Erc20 *Erc20Filterer) WatchTransfer(opts *bind.WatchOpts, sink chan<- *Erc20Transfer, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _Erc20.contract.WatchLogs(opts, "Transfer", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(Erc20Transfer) + if err := _Erc20.contract.UnpackLog(event, "Transfer", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseTransfer is a log parse operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. +// +// Solidity: event Transfer(address indexed from, address indexed to, uint256 value) +func (_Erc20 *Erc20Filterer) ParseTransfer(log types.Log) (*Erc20Transfer, error) { + event := new(Erc20Transfer) + if err := _Erc20.contract.UnpackLog(event, "Transfer", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/client/grpc/query/connection.go b/client/grpc/query/connection.go index c80144d2..2bf2b5fd 100644 --- a/client/grpc/query/connection.go +++ b/client/grpc/query/connection.go @@ -6,6 +6,8 @@ import ( "fmt" "net/url" + "github.com/0glabs/0g-chain/app" + "github.com/cosmos/cosmos-sdk/codec" "google.golang.org/grpc" "google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials/insecure" @@ -28,8 +30,20 @@ func newGrpcConnection(ctx context.Context, endpoint string) (*grpc.ClientConn, return nil, fmt.Errorf("unknown grpc url scheme: %s", grpcUrl.Scheme) } + // Ensure the encoding config is set up correctly with the query client + // otherwise it will produce panics like: + // invalid Go type math.Int for field ... + encodingConfig := app.MakeEncodingConfig() + protoCodec := codec.NewProtoCodec(encodingConfig.InterfaceRegistry) + grpcCodec := protoCodec.GRPCCodec() + secureOpt := grpc.WithTransportCredentials(creds) - grpcConn, err := grpc.DialContext(ctx, grpcUrl.Host, secureOpt) + grpcConn, err := grpc.DialContext( + ctx, + grpcUrl.Host, + secureOpt, + grpc.WithDefaultCallOptions(grpc.ForceCodec(grpcCodec)), + ) if err != nil { return nil, err } diff --git a/client/grpc/query/query.go b/client/grpc/query/query.go index 99f37fa9..7dfaaa00 100644 --- a/client/grpc/query/query.go +++ b/client/grpc/query/query.go @@ -28,6 +28,7 @@ import ( committeetypes "github.com/0glabs/0g-chain/x/committee/types" evmutiltypes "github.com/0glabs/0g-chain/x/evmutil/types" issuancetypes "github.com/0glabs/0g-chain/x/issuance/types" + precisebanktypes "github.com/0glabs/0g-chain/x/precisebank/types" pricefeedtypes "github.com/0glabs/0g-chain/x/pricefeed/types" ) @@ -60,11 +61,12 @@ type QueryClient struct { // kava module query clients - Bep3 bep3types.QueryClient - Committee committeetypes.QueryClient - Evmutil evmutiltypes.QueryClient - Issuance issuancetypes.QueryClient - Pricefeed pricefeedtypes.QueryClient + Bep3 bep3types.QueryClient + Committee committeetypes.QueryClient + Evmutil evmutiltypes.QueryClient + Issuance issuancetypes.QueryClient + Pricefeed pricefeedtypes.QueryClient + Precisebank precisebanktypes.QueryClient } // NewQueryClient creates a new QueryClient and initializes all the module query clients @@ -95,11 +97,12 @@ func NewQueryClient(grpcEndpoint string) (*QueryClient, error) { IbcClient: ibcclienttypes.NewQueryClient(conn), IbcTransfer: ibctransfertypes.NewQueryClient(conn), - Bep3: bep3types.NewQueryClient(conn), - Committee: committeetypes.NewQueryClient(conn), - Evmutil: evmutiltypes.NewQueryClient(conn), - Issuance: issuancetypes.NewQueryClient(conn), - Pricefeed: pricefeedtypes.NewQueryClient(conn), + Bep3: bep3types.NewQueryClient(conn), + Committee: committeetypes.NewQueryClient(conn), + Evmutil: evmutiltypes.NewQueryClient(conn), + Issuance: issuancetypes.NewQueryClient(conn), + Pricefeed: pricefeedtypes.NewQueryClient(conn), + Precisebank: precisebanktypes.NewQueryClient(conn), } return client, nil } diff --git a/cmd/0gchaind/app.go b/cmd/0gchaind/app.go index 4ef02853..89a9366e 100644 --- a/cmd/0gchaind/app.go +++ b/cmd/0gchaind/app.go @@ -7,6 +7,7 @@ import ( "path/filepath" "strings" + "github.com/Kava-Labs/opendb" cometbftdb "github.com/cometbft/cometbft-db" "github.com/cometbft/cometbft/libs/log" tmtypes "github.com/cometbft/cometbft/types" @@ -63,7 +64,7 @@ func (ac appCreator) newApp( homeDir := cast.ToString(appOpts.Get(flags.FlagHome)) snapshotDir := filepath.Join(homeDir, "data", "snapshots") // TODO can these directory names be imported from somewhere? - snapshotDB, err := cometbftdb.NewDB("metadata", server.GetAppDBBackend(appOpts), snapshotDir) + snapshotDB, err := opendb.OpenDB(appOpts, snapshotDir, "metadata", server.GetAppDBBackend(appOpts)) if err != nil { panic(err) } diff --git a/cmd/0gchaind/iavlviewer/data.go b/cmd/0gchaind/iavlviewer/data.go index 6dd63c76..1098a958 100644 --- a/cmd/0gchaind/iavlviewer/data.go +++ b/cmd/0gchaind/iavlviewer/data.go @@ -31,10 +31,7 @@ func newDataCmd(opts ethermintserver.StartOptions) *cobra.Command { } printKeys(tree) - hash, err := tree.Hash() - if err != nil { - return err - } + hash := tree.Hash() fmt.Printf("Hash: %X\n", hash) fmt.Printf("Size: %X\n", tree.Size()) diff --git a/cmd/0gchaind/iavlviewer/hash.go b/cmd/0gchaind/iavlviewer/hash.go index 7e411d32..9fd1d379 100644 --- a/cmd/0gchaind/iavlviewer/hash.go +++ b/cmd/0gchaind/iavlviewer/hash.go @@ -28,11 +28,7 @@ func newHashCmd(opts ethermintserver.StartOptions) *cobra.Command { return err } - hash, err := tree.Hash() - if err != nil { - return err - } - fmt.Printf("Hash: %X\n", hash) + fmt.Printf("Hash: %X\n", tree.Hash()) return nil }, diff --git a/cmd/0gchaind/iavlviewer/root.go b/cmd/0gchaind/iavlviewer/root.go index 822104bd..ea96e01f 100644 --- a/cmd/0gchaind/iavlviewer/root.go +++ b/cmd/0gchaind/iavlviewer/root.go @@ -2,15 +2,19 @@ package iavlviewer import ( "fmt" + "os" "strconv" - dbm "github.com/cometbft/cometbft-db" + "cosmossdk.io/log" + dbm "github.com/cosmos/cosmos-db" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/server" + "github.com/cosmos/cosmos-sdk/store/wrapper" ethermintserver "github.com/evmos/ethermint/server" "github.com/spf13/cobra" "github.com/cosmos/iavl" + iavldb "github.com/cosmos/iavl/db" ) const ( @@ -54,7 +58,9 @@ func openPrefixTree(opts ethermintserver.StartOptions, cmd *cobra.Command, prefi } }() - tree, err := readTree(db, version, []byte(prefix)) + cosmosdb := wrapper.NewCosmosDB(db) + + tree, err := readTree(cosmosdb, version, []byte(prefix)) if err != nil { return nil, fmt.Errorf("failed to read tree with prefix %s: %s", prefix, err) } @@ -69,10 +75,7 @@ func readTree(db dbm.DB, version int, prefix []byte) (*iavl.MutableTree, error) db = dbm.NewPrefixDB(db, prefix) } - tree, err := iavl.NewMutableTree(db, DefaultCacheSize, false) - if err != nil { - return nil, err - } + tree := iavl.NewMutableTree(iavldb.NewWrapper(db), DefaultCacheSize, false, log.NewLogger(os.Stdout)) ver, err := tree.LoadVersion(int64(version)) if err != nil { return nil, err diff --git a/cmd/0gchaind/rocksdb/compact.go b/cmd/0gchaind/rocksdb/compact.go index dc3721e1..a784ada7 100644 --- a/cmd/0gchaind/rocksdb/compact.go +++ b/cmd/0gchaind/rocksdb/compact.go @@ -14,14 +14,14 @@ import ( "syscall" "time" - "github.com/0glabs/0g-chain/cmd/opendb" + "github.com/cometbft/cometbft/libs/log" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/server" "github.com/linxGnu/grocksdb" "github.com/spf13/cobra" "golang.org/x/exp/slices" - "github.com/cometbft/cometbft/libs/log" + "github.com/Kava-Labs/opendb" ) const ( diff --git a/cmd/0gchaind/root.go b/cmd/0gchaind/root.go index ce4a769b..d9a429e5 100644 --- a/cmd/0gchaind/root.go +++ b/cmd/0gchaind/root.go @@ -3,16 +3,18 @@ package main import ( "fmt" "os" + "path/filepath" + dbm "github.com/cometbft/cometbft-db" + tmcfg "github.com/cometbft/cometbft/config" + tmcli "github.com/cometbft/cometbft/libs/cli" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/config" "github.com/cosmos/cosmos-sdk/client/debug" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/server" - - tmcfg "github.com/cometbft/cometbft/config" - tmcli "github.com/cometbft/cometbft/libs/cli" + servertypes "github.com/cosmos/cosmos-sdk/server/types" "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/genutil" @@ -29,8 +31,8 @@ import ( "github.com/0glabs/0g-chain/chaincfg" "github.com/0glabs/0g-chain/cmd/0gchaind/iavlviewer" "github.com/0glabs/0g-chain/cmd/0gchaind/rocksdb" - "github.com/0glabs/0g-chain/cmd/opendb" "github.com/0glabs/0g-chain/crypto/vrf" + "github.com/Kava-Labs/opendb" ) func customKeyringOptions() keyring.Option { @@ -52,7 +54,7 @@ func NewRootCmd() *cobra.Command { WithAccountRetriever(types.AccountRetriever{}). WithBroadcastMode(flags.FlagBroadcastMode). WithHomeDir(chaincfg.DefaultNodeHome). - WithKeyringOptions(customKeyringOptions()). + WithKeyringOptions(hd.EthSecp256k1Option()). WithViper(chaincfg.EnvPrefix) rootCmd := &cobra.Command{ Use: chaincfg.AppName, @@ -90,7 +92,14 @@ func NewRootCmd() *cobra.Command { return rootCmd } -// addSubCmds registers all the sub commands used by 0g-chain. +// dbOpener is a function to open `application.db`, potentially with customized options. +// dbOpener sets dataDir to "data", dbName to "application" and calls generic OpenDB function. +func dbOpener(opts servertypes.AppOptions, rootDir string, backend dbm.BackendType) (dbm.DB, error) { + dataDir := filepath.Join(rootDir, "data") + return opendb.OpenDB(opts, dataDir, "application", backend) +} + +// addSubCmds registers all the sub commands used by kava. func addSubCmds(rootCmd *cobra.Command, encodingConfig params.EncodingConfig, defaultNodeHome string) { gentxModule, ok := app.ModuleBasics[genutiltypes.ModuleName].(genutil.AppModuleBasic) if !ok { @@ -120,7 +129,7 @@ func addSubCmds(rootCmd *cobra.Command, encodingConfig params.EncodingConfig, de opts := ethermintserver.StartOptions{ AppCreator: ac.newApp, DefaultNodeHome: chaincfg.DefaultNodeHome, - DBOpener: opendb.OpenDB, + DBOpener: dbOpener, } // ethermintserver adds additional flags to start the JSON-RPC server for evm support ethermintserver.AddCommands( diff --git a/cmd/0gchaind/shard.go b/cmd/0gchaind/shard.go index 7840f353..e07f7e3c 100644 --- a/cmd/0gchaind/shard.go +++ b/cmd/0gchaind/shard.go @@ -219,9 +219,12 @@ func shardApplicationDb(multistore *rootmulti.Store, startBlock, endBlock int64) } if len(pruneHeights) > 0 { + // prune application state fmt.Printf("pruning application state to height %d\n", startBlock) - if err := multistore.PruneStores(true, pruneHeights); err != nil { - return fmt.Errorf("failed to prune application state: %s", err) + for _, pruneHeight := range pruneHeights { + if err := multistore.PruneStores(pruneHeight); err != nil { + return fmt.Errorf("failed to prune application state: %s", err) + } } } diff --git a/cmd/opendb/metrics.go b/cmd/opendb/metrics.go deleted file mode 100644 index dc7fd8de..00000000 --- a/cmd/opendb/metrics.go +++ /dev/null @@ -1,499 +0,0 @@ -//go:build rocksdb -// +build rocksdb - -package opendb - -import ( - "github.com/go-kit/kit/metrics" - "github.com/go-kit/kit/metrics/prometheus" - stdprometheus "github.com/prometheus/client_golang/prometheus" -) - -// rocksdbMetrics will be initialized in registerMetrics() if enableRocksdbMetrics flag set to true -var rocksdbMetrics *Metrics - -// Metrics contains all rocksdb metrics which will be reported to prometheus -type Metrics struct { - // Keys - NumberKeysWritten metrics.Gauge - NumberKeysRead metrics.Gauge - NumberKeysUpdated metrics.Gauge - EstimateNumKeys metrics.Gauge - - // Files - NumberFileOpens metrics.Gauge - NumberFileErrors metrics.Gauge - - // Memory - BlockCacheUsage metrics.Gauge - EstimateTableReadersMem metrics.Gauge - CurSizeAllMemTables metrics.Gauge - BlockCachePinnedUsage metrics.Gauge - - // Cache - BlockCacheMiss metrics.Gauge - BlockCacheHit metrics.Gauge - BlockCacheAdd metrics.Gauge - BlockCacheAddFailures metrics.Gauge - - // Detailed Cache - BlockCacheIndexMiss metrics.Gauge - BlockCacheIndexHit metrics.Gauge - BlockCacheIndexBytesInsert metrics.Gauge - - BlockCacheFilterMiss metrics.Gauge - BlockCacheFilterHit metrics.Gauge - BlockCacheFilterBytesInsert metrics.Gauge - - BlockCacheDataMiss metrics.Gauge - BlockCacheDataHit metrics.Gauge - BlockCacheDataBytesInsert metrics.Gauge - - // Latency - DBGetMicrosP50 metrics.Gauge - DBGetMicrosP95 metrics.Gauge - DBGetMicrosP99 metrics.Gauge - DBGetMicrosP100 metrics.Gauge - DBGetMicrosCount metrics.Gauge - - DBWriteMicrosP50 metrics.Gauge - DBWriteMicrosP95 metrics.Gauge - DBWriteMicrosP99 metrics.Gauge - DBWriteMicrosP100 metrics.Gauge - DBWriteMicrosCount metrics.Gauge - - // Write Stall - StallMicros metrics.Gauge - - DBWriteStallP50 metrics.Gauge - DBWriteStallP95 metrics.Gauge - DBWriteStallP99 metrics.Gauge - DBWriteStallP100 metrics.Gauge - DBWriteStallCount metrics.Gauge - DBWriteStallSum metrics.Gauge - - // Bloom Filter - BloomFilterUseful metrics.Gauge - BloomFilterFullPositive metrics.Gauge - BloomFilterFullTruePositive metrics.Gauge - - // LSM Tree Stats - LastLevelReadBytes metrics.Gauge - LastLevelReadCount metrics.Gauge - NonLastLevelReadBytes metrics.Gauge - NonLastLevelReadCount metrics.Gauge - - GetHitL0 metrics.Gauge - GetHitL1 metrics.Gauge - GetHitL2AndUp metrics.Gauge -} - -// registerMetrics registers metrics in prometheus and initializes rocksdbMetrics variable -func registerMetrics() { - if rocksdbMetrics != nil { - // metrics already registered - return - } - - labels := make([]string, 0) - rocksdbMetrics = &Metrics{ - // Keys - NumberKeysWritten: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "key", - Name: "number_keys_written", - Help: "", - }, labels), - NumberKeysRead: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "key", - Name: "number_keys_read", - Help: "", - }, labels), - NumberKeysUpdated: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "key", - Name: "number_keys_updated", - Help: "", - }, labels), - EstimateNumKeys: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "key", - Name: "estimate_num_keys", - Help: "estimated number of total keys in the active and unflushed immutable memtables and storage", - }, labels), - - // Files - NumberFileOpens: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "file", - Name: "number_file_opens", - Help: "", - }, labels), - NumberFileErrors: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "file", - Name: "number_file_errors", - Help: "", - }, labels), - - // Memory - BlockCacheUsage: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "memory", - Name: "block_cache_usage", - Help: "memory size for the entries residing in block cache", - }, labels), - EstimateTableReadersMem: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "memory", - Name: "estimate_table_readers_mem", - Help: "estimated memory used for reading SST tables, excluding memory used in block cache (e.g., filter and index blocks)", - }, labels), - CurSizeAllMemTables: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "memory", - Name: "cur_size_all_mem_tables", - Help: "approximate size of active and unflushed immutable memtables (bytes)", - }, labels), - BlockCachePinnedUsage: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "memory", - Name: "block_cache_pinned_usage", - Help: "returns the memory size for the entries being pinned", - }, labels), - - // Cache - BlockCacheMiss: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "cache", - Name: "block_cache_miss", - Help: "block_cache_miss == block_cache_index_miss + block_cache_filter_miss + block_cache_data_miss", - }, labels), - BlockCacheHit: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "cache", - Name: "block_cache_hit", - Help: "block_cache_hit == block_cache_index_hit + block_cache_filter_hit + block_cache_data_hit", - }, labels), - BlockCacheAdd: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "cache", - Name: "block_cache_add", - Help: "number of blocks added to block cache", - }, labels), - BlockCacheAddFailures: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "cache", - Name: "block_cache_add_failures", - Help: "number of failures when adding blocks to block cache", - }, labels), - - // Detailed Cache - BlockCacheIndexMiss: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "detailed_cache", - Name: "block_cache_index_miss", - Help: "", - }, labels), - BlockCacheIndexHit: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "detailed_cache", - Name: "block_cache_index_hit", - Help: "", - }, labels), - BlockCacheIndexBytesInsert: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "detailed_cache", - Name: "block_cache_index_bytes_insert", - Help: "", - }, labels), - - BlockCacheFilterMiss: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "detailed_cache", - Name: "block_cache_filter_miss", - Help: "", - }, labels), - BlockCacheFilterHit: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "detailed_cache", - Name: "block_cache_filter_hit", - Help: "", - }, labels), - BlockCacheFilterBytesInsert: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "detailed_cache", - Name: "block_cache_filter_bytes_insert", - Help: "", - }, labels), - - BlockCacheDataMiss: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "detailed_cache", - Name: "block_cache_data_miss", - Help: "", - }, labels), - BlockCacheDataHit: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "detailed_cache", - Name: "block_cache_data_hit", - Help: "", - }, labels), - BlockCacheDataBytesInsert: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "detailed_cache", - Name: "block_cache_data_bytes_insert", - Help: "", - }, labels), - - // Latency - DBGetMicrosP50: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "latency", - Name: "db_get_micros_p50", - Help: "", - }, labels), - DBGetMicrosP95: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "latency", - Name: "db_get_micros_p95", - Help: "", - }, labels), - DBGetMicrosP99: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "latency", - Name: "db_get_micros_p99", - Help: "", - }, labels), - DBGetMicrosP100: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "latency", - Name: "db_get_micros_p100", - Help: "", - }, labels), - DBGetMicrosCount: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "latency", - Name: "db_get_micros_count", - Help: "", - }, labels), - - DBWriteMicrosP50: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "latency", - Name: "db_write_micros_p50", - Help: "", - }, labels), - DBWriteMicrosP95: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "latency", - Name: "db_write_micros_p95", - Help: "", - }, labels), - DBWriteMicrosP99: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "latency", - Name: "db_write_micros_p99", - Help: "", - }, labels), - DBWriteMicrosP100: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "latency", - Name: "db_write_micros_p100", - Help: "", - }, labels), - DBWriteMicrosCount: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "latency", - Name: "db_write_micros_count", - Help: "", - }, labels), - - // Write Stall - StallMicros: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "stall", - Name: "stall_micros", - Help: "Writer has to wait for compaction or flush to finish.", - }, labels), - - DBWriteStallP50: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "stall", - Name: "db_write_stall_p50", - Help: "", - }, labels), - DBWriteStallP95: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "stall", - Name: "db_write_stall_p95", - Help: "", - }, labels), - DBWriteStallP99: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "stall", - Name: "db_write_stall_p99", - Help: "", - }, labels), - DBWriteStallP100: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "stall", - Name: "db_write_stall_p100", - Help: "", - }, labels), - DBWriteStallCount: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "stall", - Name: "db_write_stall_count", - Help: "", - }, labels), - DBWriteStallSum: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "stall", - Name: "db_write_stall_sum", - Help: "", - }, labels), - - // Bloom Filter - BloomFilterUseful: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "filter", - Name: "bloom_filter_useful", - Help: "number of times bloom filter has avoided file reads, i.e., negatives.", - }, labels), - BloomFilterFullPositive: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "filter", - Name: "bloom_filter_full_positive", - Help: "number of times bloom FullFilter has not avoided the reads.", - }, labels), - BloomFilterFullTruePositive: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "filter", - Name: "bloom_filter_full_true_positive", - Help: "number of times bloom FullFilter has not avoided the reads and data actually exist.", - }, labels), - - // LSM Tree Stats - LastLevelReadBytes: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "lsm", - Name: "last_level_read_bytes", - Help: "", - }, labels), - LastLevelReadCount: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "lsm", - Name: "last_level_read_count", - Help: "", - }, labels), - NonLastLevelReadBytes: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "lsm", - Name: "non_last_level_read_bytes", - Help: "", - }, labels), - NonLastLevelReadCount: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "lsm", - Name: "non_last_level_read_count", - Help: "", - }, labels), - - GetHitL0: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "lsm", - Name: "get_hit_l0", - Help: "number of Get() queries served by L0", - }, labels), - GetHitL1: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "lsm", - Name: "get_hit_l1", - Help: "number of Get() queries served by L1", - }, labels), - GetHitL2AndUp: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: "rocksdb", - Subsystem: "lsm", - Name: "get_hit_l2_and_up", - Help: "number of Get() queries served by L2 and up", - }, labels), - } -} - -// report reports metrics to prometheus based on rocksdb props and stats -func (m *Metrics) report(props *properties, stats *stats) { - // Keys - m.NumberKeysWritten.Set(float64(stats.NumberKeysWritten)) - m.NumberKeysRead.Set(float64(stats.NumberKeysRead)) - m.NumberKeysUpdated.Set(float64(stats.NumberKeysUpdated)) - m.EstimateNumKeys.Set(float64(props.EstimateNumKeys)) - - // Files - m.NumberFileOpens.Set(float64(stats.NumberFileOpens)) - m.NumberFileErrors.Set(float64(stats.NumberFileErrors)) - - // Memory - m.BlockCacheUsage.Set(float64(props.BlockCacheUsage)) - m.EstimateTableReadersMem.Set(float64(props.EstimateTableReadersMem)) - m.CurSizeAllMemTables.Set(float64(props.CurSizeAllMemTables)) - m.BlockCachePinnedUsage.Set(float64(props.BlockCachePinnedUsage)) - - // Cache - m.BlockCacheMiss.Set(float64(stats.BlockCacheMiss)) - m.BlockCacheHit.Set(float64(stats.BlockCacheHit)) - m.BlockCacheAdd.Set(float64(stats.BlockCacheAdd)) - m.BlockCacheAddFailures.Set(float64(stats.BlockCacheAddFailures)) - - // Detailed Cache - m.BlockCacheIndexMiss.Set(float64(stats.BlockCacheIndexMiss)) - m.BlockCacheIndexHit.Set(float64(stats.BlockCacheIndexHit)) - m.BlockCacheIndexBytesInsert.Set(float64(stats.BlockCacheIndexBytesInsert)) - - m.BlockCacheFilterMiss.Set(float64(stats.BlockCacheFilterMiss)) - m.BlockCacheFilterHit.Set(float64(stats.BlockCacheFilterHit)) - m.BlockCacheFilterBytesInsert.Set(float64(stats.BlockCacheFilterBytesInsert)) - - m.BlockCacheDataMiss.Set(float64(stats.BlockCacheDataMiss)) - m.BlockCacheDataHit.Set(float64(stats.BlockCacheDataHit)) - m.BlockCacheDataBytesInsert.Set(float64(stats.BlockCacheDataBytesInsert)) - - // Latency - m.DBGetMicrosP50.Set(stats.DBGetMicros.P50) - m.DBGetMicrosP95.Set(stats.DBGetMicros.P95) - m.DBGetMicrosP99.Set(stats.DBGetMicros.P99) - m.DBGetMicrosP100.Set(stats.DBGetMicros.P100) - m.DBGetMicrosCount.Set(stats.DBGetMicros.Count) - - m.DBWriteMicrosP50.Set(stats.DBWriteMicros.P50) - m.DBWriteMicrosP95.Set(stats.DBWriteMicros.P95) - m.DBWriteMicrosP99.Set(stats.DBWriteMicros.P99) - m.DBWriteMicrosP100.Set(stats.DBWriteMicros.P100) - m.DBWriteMicrosCount.Set(stats.DBWriteMicros.Count) - - // Write Stall - m.StallMicros.Set(float64(stats.StallMicros)) - - m.DBWriteStallP50.Set(stats.DBWriteStallHistogram.P50) - m.DBWriteStallP95.Set(stats.DBWriteStallHistogram.P95) - m.DBWriteStallP99.Set(stats.DBWriteStallHistogram.P99) - m.DBWriteStallP100.Set(stats.DBWriteStallHistogram.P100) - m.DBWriteStallCount.Set(stats.DBWriteStallHistogram.Count) - m.DBWriteStallSum.Set(stats.DBWriteStallHistogram.Sum) - - // Bloom Filter - m.BloomFilterUseful.Set(float64(stats.BloomFilterUseful)) - m.BloomFilterFullPositive.Set(float64(stats.BloomFilterFullPositive)) - m.BloomFilterFullTruePositive.Set(float64(stats.BloomFilterFullTruePositive)) - - // LSM Tree Stats - m.LastLevelReadBytes.Set(float64(stats.LastLevelReadBytes)) - m.LastLevelReadCount.Set(float64(stats.LastLevelReadCount)) - m.NonLastLevelReadBytes.Set(float64(stats.NonLastLevelReadBytes)) - m.NonLastLevelReadCount.Set(float64(stats.NonLastLevelReadCount)) - - m.GetHitL0.Set(float64(stats.GetHitL0)) - m.GetHitL1.Set(float64(stats.GetHitL1)) - m.GetHitL2AndUp.Set(float64(stats.GetHitL2AndUp)) -} diff --git a/cmd/opendb/opendb.go b/cmd/opendb/opendb.go deleted file mode 100644 index 35e49abb..00000000 --- a/cmd/opendb/opendb.go +++ /dev/null @@ -1,18 +0,0 @@ -//go:build !rocksdb -// +build !rocksdb - -package opendb - -import ( - "path/filepath" - - dbm "github.com/cometbft/cometbft-db" - "github.com/cosmos/cosmos-sdk/server/types" -) - -// OpenDB is a copy of default DBOpener function used by ethermint, see for details: -// https://github.com/evmos/ethermint/blob/07cf2bd2b1ce9bdb2e44ec42a39e7239292a14af/server/start.go#L647 -func OpenDB(_ types.AppOptions, home string, backendType dbm.BackendType) (dbm.DB, error) { - dataDir := filepath.Join(home, "data") - return dbm.NewDB("application", backendType, dataDir) -} diff --git a/cmd/opendb/opendb_rocksdb.go b/cmd/opendb/opendb_rocksdb.go deleted file mode 100644 index d4c8f956..00000000 --- a/cmd/opendb/opendb_rocksdb.go +++ /dev/null @@ -1,398 +0,0 @@ -//go:build rocksdb -// +build rocksdb - -// Copyright 2023 Kava Labs, Inc. -// Copyright 2023 Cronos Labs, Inc. -// -// Derived from https://github.com/crypto-org-chain/cronos@496ce7e -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package opendb - -import ( - "errors" - "fmt" - "os" - "path/filepath" - "runtime" - "strings" - "time" - - dbm "github.com/cometbft/cometbft-db" - "github.com/cosmos/cosmos-sdk/server/types" - "github.com/linxGnu/grocksdb" - "github.com/spf13/cast" -) - -var ErrUnexpectedConfiguration = errors.New("unexpected rocksdb configuration, rocksdb should have only one column family named default") - -const ( - // default tm-db block cache size for RocksDB - defaultBlockCacheSize = 1 << 30 - - DefaultColumnFamilyName = "default" - - enableMetricsOptName = "rocksdb.enable-metrics" - reportMetricsIntervalSecsOptName = "rocksdb.report-metrics-interval-secs" - defaultReportMetricsIntervalSecs = 15 - - maxOpenFilesDBOptName = "rocksdb.max-open-files" - maxFileOpeningThreadsDBOptName = "rocksdb.max-file-opening-threads" - tableCacheNumshardbitsDBOptName = "rocksdb.table_cache_numshardbits" - allowMMAPWritesDBOptName = "rocksdb.allow_mmap_writes" - allowMMAPReadsDBOptName = "rocksdb.allow_mmap_reads" - useFsyncDBOptName = "rocksdb.use_fsync" - useAdaptiveMutexDBOptName = "rocksdb.use_adaptive_mutex" - bytesPerSyncDBOptName = "rocksdb.bytes_per_sync" - maxBackgroundJobsDBOptName = "rocksdb.max-background-jobs" - - writeBufferSizeCFOptName = "rocksdb.write-buffer-size" - numLevelsCFOptName = "rocksdb.num-levels" - maxWriteBufferNumberCFOptName = "rocksdb.max_write_buffer_number" - minWriteBufferNumberToMergeCFOptName = "rocksdb.min_write_buffer_number_to_merge" - maxBytesForLevelBaseCFOptName = "rocksdb.max_bytes_for_level_base" - maxBytesForLevelMultiplierCFOptName = "rocksdb.max_bytes_for_level_multiplier" - targetFileSizeBaseCFOptName = "rocksdb.target_file_size_base" - targetFileSizeMultiplierCFOptName = "rocksdb.target_file_size_multiplier" - level0FileNumCompactionTriggerCFOptName = "rocksdb.level0_file_num_compaction_trigger" - level0SlowdownWritesTriggerCFOptName = "rocksdb.level0_slowdown_writes_trigger" - - blockCacheSizeBBTOOptName = "rocksdb.block_cache_size" - bitsPerKeyBBTOOptName = "rocksdb.bits_per_key" - blockSizeBBTOOptName = "rocksdb.block_size" - cacheIndexAndFilterBlocksBBTOOptName = "rocksdb.cache_index_and_filter_blocks" - pinL0FilterAndIndexBlocksInCacheBBTOOptName = "rocksdb.pin_l0_filter_and_index_blocks_in_cache" - formatVersionBBTOOptName = "rocksdb.format_version" - - asyncIOReadOptName = "rocksdb.read-async-io" -) - -func OpenDB(appOpts types.AppOptions, home string, backendType dbm.BackendType) (dbm.DB, error) { - dataDir := filepath.Join(home, "data") - if backendType == dbm.RocksDBBackend { - return openRocksdb(dataDir, appOpts) - } - - return dbm.NewDB("application", backendType, dataDir) -} - -// openRocksdb loads existing options, overrides some of them with appOpts and opens database -// option will be overridden only in case if it explicitly specified in appOpts -func openRocksdb(dir string, appOpts types.AppOptions) (dbm.DB, error) { - optionsPath := filepath.Join(dir, "application.db") - dbOpts, cfOpts, err := LoadLatestOptions(optionsPath) - if err != nil { - return nil, err - } - // customize rocksdb options - bbtoOpts := bbtoFromAppOpts(appOpts) - dbOpts.SetBlockBasedTableFactory(bbtoOpts) - cfOpts.SetBlockBasedTableFactory(bbtoOpts) - dbOpts = overrideDBOpts(dbOpts, appOpts) - cfOpts = overrideCFOpts(cfOpts, appOpts) - readOpts := readOptsFromAppOpts(appOpts) - - enableMetrics := cast.ToBool(appOpts.Get(enableMetricsOptName)) - reportMetricsIntervalSecs := cast.ToInt64(appOpts.Get(reportMetricsIntervalSecsOptName)) - if reportMetricsIntervalSecs == 0 { - reportMetricsIntervalSecs = defaultReportMetricsIntervalSecs - } - - return newRocksDBWithOptions("application", dir, dbOpts, cfOpts, readOpts, enableMetrics, reportMetricsIntervalSecs) -} - -// LoadLatestOptions loads and returns database and column family options -// if options file not found, it means database isn't created yet, in such case default tm-db options will be returned -// if database exists it should have only one column family named default -func LoadLatestOptions(dir string) (*grocksdb.Options, *grocksdb.Options, error) { - latestOpts, err := grocksdb.LoadLatestOptions(dir, grocksdb.NewDefaultEnv(), true, grocksdb.NewLRUCache(defaultBlockCacheSize)) - if err != nil && strings.HasPrefix(err.Error(), "NotFound: ") { - return newDefaultOptions(), newDefaultOptions(), nil - } - if err != nil { - return nil, nil, err - } - - cfNames := latestOpts.ColumnFamilyNames() - cfOpts := latestOpts.ColumnFamilyOpts() - // db should have only one column family named default - ok := len(cfNames) == 1 && cfNames[0] == DefaultColumnFamilyName - if !ok { - return nil, nil, ErrUnexpectedConfiguration - } - - // return db and cf opts - return latestOpts.Options(), &cfOpts[0], nil -} - -// overrideDBOpts merges dbOpts and appOpts, appOpts takes precedence -func overrideDBOpts(dbOpts *grocksdb.Options, appOpts types.AppOptions) *grocksdb.Options { - maxOpenFiles := appOpts.Get(maxOpenFilesDBOptName) - if maxOpenFiles != nil { - dbOpts.SetMaxOpenFiles(cast.ToInt(maxOpenFiles)) - } - - maxFileOpeningThreads := appOpts.Get(maxFileOpeningThreadsDBOptName) - if maxFileOpeningThreads != nil { - dbOpts.SetMaxFileOpeningThreads(cast.ToInt(maxFileOpeningThreads)) - } - - tableCacheNumshardbits := appOpts.Get(tableCacheNumshardbitsDBOptName) - if tableCacheNumshardbits != nil { - dbOpts.SetTableCacheNumshardbits(cast.ToInt(tableCacheNumshardbits)) - } - - allowMMAPWrites := appOpts.Get(allowMMAPWritesDBOptName) - if allowMMAPWrites != nil { - dbOpts.SetAllowMmapWrites(cast.ToBool(allowMMAPWrites)) - } - - allowMMAPReads := appOpts.Get(allowMMAPReadsDBOptName) - if allowMMAPReads != nil { - dbOpts.SetAllowMmapReads(cast.ToBool(allowMMAPReads)) - } - - useFsync := appOpts.Get(useFsyncDBOptName) - if useFsync != nil { - dbOpts.SetUseFsync(cast.ToBool(useFsync)) - } - - useAdaptiveMutex := appOpts.Get(useAdaptiveMutexDBOptName) - if useAdaptiveMutex != nil { - dbOpts.SetUseAdaptiveMutex(cast.ToBool(useAdaptiveMutex)) - } - - bytesPerSync := appOpts.Get(bytesPerSyncDBOptName) - if bytesPerSync != nil { - dbOpts.SetBytesPerSync(cast.ToUint64(bytesPerSync)) - } - - maxBackgroundJobs := appOpts.Get(maxBackgroundJobsDBOptName) - if maxBackgroundJobs != nil { - dbOpts.SetMaxBackgroundJobs(cast.ToInt(maxBackgroundJobs)) - } - - return dbOpts -} - -// overrideCFOpts merges cfOpts and appOpts, appOpts takes precedence -func overrideCFOpts(cfOpts *grocksdb.Options, appOpts types.AppOptions) *grocksdb.Options { - writeBufferSize := appOpts.Get(writeBufferSizeCFOptName) - if writeBufferSize != nil { - cfOpts.SetWriteBufferSize(cast.ToUint64(writeBufferSize)) - } - - numLevels := appOpts.Get(numLevelsCFOptName) - if numLevels != nil { - cfOpts.SetNumLevels(cast.ToInt(numLevels)) - } - - maxWriteBufferNumber := appOpts.Get(maxWriteBufferNumberCFOptName) - if maxWriteBufferNumber != nil { - cfOpts.SetMaxWriteBufferNumber(cast.ToInt(maxWriteBufferNumber)) - } - - minWriteBufferNumberToMerge := appOpts.Get(minWriteBufferNumberToMergeCFOptName) - if minWriteBufferNumberToMerge != nil { - cfOpts.SetMinWriteBufferNumberToMerge(cast.ToInt(minWriteBufferNumberToMerge)) - } - - maxBytesForLevelBase := appOpts.Get(maxBytesForLevelBaseCFOptName) - if maxBytesForLevelBase != nil { - cfOpts.SetMaxBytesForLevelBase(cast.ToUint64(maxBytesForLevelBase)) - } - - maxBytesForLevelMultiplier := appOpts.Get(maxBytesForLevelMultiplierCFOptName) - if maxBytesForLevelMultiplier != nil { - cfOpts.SetMaxBytesForLevelMultiplier(cast.ToFloat64(maxBytesForLevelMultiplier)) - } - - targetFileSizeBase := appOpts.Get(targetFileSizeBaseCFOptName) - if targetFileSizeBase != nil { - cfOpts.SetTargetFileSizeBase(cast.ToUint64(targetFileSizeBase)) - } - - targetFileSizeMultiplier := appOpts.Get(targetFileSizeMultiplierCFOptName) - if targetFileSizeMultiplier != nil { - cfOpts.SetTargetFileSizeMultiplier(cast.ToInt(targetFileSizeMultiplier)) - } - - level0FileNumCompactionTrigger := appOpts.Get(level0FileNumCompactionTriggerCFOptName) - if level0FileNumCompactionTrigger != nil { - cfOpts.SetLevel0FileNumCompactionTrigger(cast.ToInt(level0FileNumCompactionTrigger)) - } - - level0SlowdownWritesTrigger := appOpts.Get(level0SlowdownWritesTriggerCFOptName) - if level0SlowdownWritesTrigger != nil { - cfOpts.SetLevel0SlowdownWritesTrigger(cast.ToInt(level0SlowdownWritesTrigger)) - } - - return cfOpts -} - -func readOptsFromAppOpts(appOpts types.AppOptions) *grocksdb.ReadOptions { - ro := grocksdb.NewDefaultReadOptions() - asyncIO := appOpts.Get(asyncIOReadOptName) - if asyncIO != nil { - ro.SetAsyncIO(cast.ToBool(asyncIO)) - } - - return ro -} - -func bbtoFromAppOpts(appOpts types.AppOptions) *grocksdb.BlockBasedTableOptions { - bbto := defaultBBTO() - - blockCacheSize := appOpts.Get(blockCacheSizeBBTOOptName) - if blockCacheSize != nil { - cache := grocksdb.NewLRUCache(cast.ToUint64(blockCacheSize)) - bbto.SetBlockCache(cache) - } - - bitsPerKey := appOpts.Get(bitsPerKeyBBTOOptName) - if bitsPerKey != nil { - filter := grocksdb.NewBloomFilter(cast.ToFloat64(bitsPerKey)) - bbto.SetFilterPolicy(filter) - } - - blockSize := appOpts.Get(blockSizeBBTOOptName) - if blockSize != nil { - bbto.SetBlockSize(cast.ToInt(blockSize)) - } - - cacheIndexAndFilterBlocks := appOpts.Get(cacheIndexAndFilterBlocksBBTOOptName) - if cacheIndexAndFilterBlocks != nil { - bbto.SetCacheIndexAndFilterBlocks(cast.ToBool(cacheIndexAndFilterBlocks)) - } - - pinL0FilterAndIndexBlocksInCache := appOpts.Get(pinL0FilterAndIndexBlocksInCacheBBTOOptName) - if pinL0FilterAndIndexBlocksInCache != nil { - bbto.SetPinL0FilterAndIndexBlocksInCache(cast.ToBool(pinL0FilterAndIndexBlocksInCache)) - } - - formatVersion := appOpts.Get(formatVersionBBTOOptName) - if formatVersion != nil { - bbto.SetFormatVersion(cast.ToInt(formatVersion)) - } - - return bbto -} - -// newRocksDBWithOptions opens rocksdb with provided database and column family options -// newRocksDBWithOptions expects that db has only one column family named default -func newRocksDBWithOptions( - name string, - dir string, - dbOpts *grocksdb.Options, - cfOpts *grocksdb.Options, - readOpts *grocksdb.ReadOptions, - enableMetrics bool, - reportMetricsIntervalSecs int64, -) (*dbm.RocksDB, error) { - dbPath := filepath.Join(dir, name+".db") - - // Ensure path exists - if err := os.MkdirAll(dbPath, 0755); err != nil { - return nil, fmt.Errorf("failed to create db path: %w", err) - } - - // EnableStatistics adds overhead so shouldn't be enabled in production - if enableMetrics { - dbOpts.EnableStatistics() - } - - db, _, err := grocksdb.OpenDbColumnFamilies(dbOpts, dbPath, []string{DefaultColumnFamilyName}, []*grocksdb.Options{cfOpts}) - if err != nil { - return nil, err - } - - if enableMetrics { - registerMetrics() - go reportMetrics(db, time.Second*time.Duration(reportMetricsIntervalSecs)) - } - - wo := grocksdb.NewDefaultWriteOptions() - woSync := grocksdb.NewDefaultWriteOptions() - woSync.SetSync(true) - return dbm.NewRocksDBWithRawDB(db, readOpts, wo, woSync), nil -} - -// newDefaultOptions returns default tm-db options for RocksDB, see for details: -// https://github.com/Kava-Labs/tm-db/blob/94ff76d31724965f8883cddebabe91e0d01bc03f/rocksdb.go#L30 -func newDefaultOptions() *grocksdb.Options { - // default rocksdb option, good enough for most cases, including heavy workloads. - // 1GB table cache, 512MB write buffer(may use 50% more on heavy workloads). - // compression: snappy as default, need to -lsnappy to enable. - bbto := defaultBBTO() - - opts := grocksdb.NewDefaultOptions() - opts.SetBlockBasedTableFactory(bbto) - // SetMaxOpenFiles to 4096 seems to provide a reliable performance boost - opts.SetMaxOpenFiles(4096) - opts.SetCreateIfMissing(true) - opts.IncreaseParallelism(runtime.NumCPU()) - // 1.5GB maximum memory use for writebuffer. - opts.OptimizeLevelStyleCompaction(512 * 1024 * 1024) - - return opts -} - -// defaultBBTO returns default tm-db bbto options for RocksDB, see for details: -// https://github.com/Kava-Labs/tm-db/blob/94ff76d31724965f8883cddebabe91e0d01bc03f/rocksdb.go#L30 -func defaultBBTO() *grocksdb.BlockBasedTableOptions { - bbto := grocksdb.NewDefaultBlockBasedTableOptions() - bbto.SetBlockCache(grocksdb.NewLRUCache(defaultBlockCacheSize)) - bbto.SetFilterPolicy(grocksdb.NewBloomFilter(10)) - - return bbto -} - -// reportMetrics periodically requests stats from rocksdb and reports to prometheus -// NOTE: should be launched as a goroutine -func reportMetrics(db *grocksdb.DB, interval time.Duration) { - ticker := time.NewTicker(interval) - for { - select { - case <-ticker.C: - props, stats, err := getPropsAndStats(db) - if err != nil { - continue - } - - rocksdbMetrics.report(props, stats) - } - } -} - -// getPropsAndStats gets statistics from rocksdb -func getPropsAndStats(db *grocksdb.DB) (*properties, *stats, error) { - propsLoader := newPropsLoader(db) - props, err := propsLoader.load() - if err != nil { - return nil, nil, err - } - - statMap, err := parseSerializedStats(props.OptionsStatistics) - if err != nil { - return nil, nil, err - } - - statLoader := newStatLoader(statMap) - stats, err := statLoader.load() - if err != nil { - return nil, nil, err - } - - return props, stats, nil -} diff --git a/cmd/opendb/opendb_rocksdb_test.go b/cmd/opendb/opendb_rocksdb_test.go deleted file mode 100644 index a730e2dc..00000000 --- a/cmd/opendb/opendb_rocksdb_test.go +++ /dev/null @@ -1,384 +0,0 @@ -//go:build rocksdb -// +build rocksdb - -package opendb - -import ( - "os" - "path/filepath" - "testing" - - "github.com/linxGnu/grocksdb" - "github.com/stretchr/testify/require" -) - -type mockAppOptions struct { - opts map[string]interface{} -} - -func newMockAppOptions(opts map[string]interface{}) *mockAppOptions { - return &mockAppOptions{ - opts: opts, - } -} - -func (m *mockAppOptions) Get(key string) interface{} { - return m.opts[key] -} - -func TestOpenRocksdb(t *testing.T) { - t.Run("db already exists", func(t *testing.T) { - defaultOpts := newDefaultOptions() - - for _, tc := range []struct { - desc string - mockAppOptions *mockAppOptions - maxOpenFiles int - maxFileOpeningThreads int - writeBufferSize uint64 - numLevels int - }{ - { - desc: "default options", - mockAppOptions: newMockAppOptions(map[string]interface{}{}), - maxOpenFiles: defaultOpts.GetMaxOpenFiles(), - maxFileOpeningThreads: defaultOpts.GetMaxFileOpeningThreads(), - writeBufferSize: defaultOpts.GetWriteBufferSize(), - numLevels: defaultOpts.GetNumLevels(), - }, - { - desc: "change 2 options", - mockAppOptions: newMockAppOptions(map[string]interface{}{ - maxOpenFilesDBOptName: 999, - writeBufferSizeCFOptName: 999_999, - }), - maxOpenFiles: 999, - maxFileOpeningThreads: defaultOpts.GetMaxFileOpeningThreads(), - writeBufferSize: 999_999, - numLevels: defaultOpts.GetNumLevels(), - }, - { - desc: "change 4 options", - mockAppOptions: newMockAppOptions(map[string]interface{}{ - maxOpenFilesDBOptName: 999, - maxFileOpeningThreadsDBOptName: 9, - writeBufferSizeCFOptName: 999_999, - numLevelsCFOptName: 9, - }), - maxOpenFiles: 999, - maxFileOpeningThreads: 9, - writeBufferSize: 999_999, - numLevels: 9, - }, - } { - t.Run(tc.desc, func(t *testing.T) { - dir, err := os.MkdirTemp("", "rocksdb") - require.NoError(t, err) - defer func() { - err := os.RemoveAll(dir) - require.NoError(t, err) - }() - - db, err := openRocksdb(dir, tc.mockAppOptions) - require.NoError(t, err) - require.NoError(t, db.Close()) - - dbOpts, cfOpts, err := LoadLatestOptions(filepath.Join(dir, "application.db")) - require.NoError(t, err) - require.Equal(t, tc.maxOpenFiles, dbOpts.GetMaxOpenFiles()) - require.Equal(t, tc.maxFileOpeningThreads, dbOpts.GetMaxFileOpeningThreads()) - require.Equal(t, tc.writeBufferSize, cfOpts.GetWriteBufferSize()) - require.Equal(t, tc.numLevels, cfOpts.GetNumLevels()) - }) - } - }) - - t.Run("db doesn't exist yet", func(t *testing.T) { - defaultOpts := newDefaultOptions() - - dir, err := os.MkdirTemp("", "rocksdb") - require.NoError(t, err) - defer func() { - err := os.RemoveAll(dir) - require.NoError(t, err) - }() - - mockAppOpts := newMockAppOptions(map[string]interface{}{}) - db, err := openRocksdb(dir, mockAppOpts) - require.NoError(t, err) - require.NoError(t, db.Close()) - - dbOpts, cfOpts, err := LoadLatestOptions(filepath.Join(dir, "application.db")) - require.NoError(t, err) - require.Equal(t, defaultOpts.GetMaxOpenFiles(), dbOpts.GetMaxOpenFiles()) - require.Equal(t, defaultOpts.GetMaxFileOpeningThreads(), dbOpts.GetMaxFileOpeningThreads()) - require.Equal(t, defaultOpts.GetWriteBufferSize(), cfOpts.GetWriteBufferSize()) - require.Equal(t, defaultOpts.GetNumLevels(), cfOpts.GetNumLevels()) - }) -} - -func TestLoadLatestOptions(t *testing.T) { - t.Run("db already exists", func(t *testing.T) { - defaultOpts := newDefaultOptions() - - const testCasesNum = 3 - dbOptsList := make([]*grocksdb.Options, testCasesNum) - cfOptsList := make([]*grocksdb.Options, testCasesNum) - - dbOptsList[0] = newDefaultOptions() - cfOptsList[0] = newDefaultOptions() - - dbOptsList[1] = newDefaultOptions() - dbOptsList[1].SetMaxOpenFiles(999) - cfOptsList[1] = newDefaultOptions() - cfOptsList[1].SetWriteBufferSize(999_999) - - dbOptsList[2] = newDefaultOptions() - dbOptsList[2].SetMaxOpenFiles(999) - dbOptsList[2].SetMaxFileOpeningThreads(9) - cfOptsList[2] = newDefaultOptions() - cfOptsList[2].SetWriteBufferSize(999_999) - cfOptsList[2].SetNumLevels(9) - - for _, tc := range []struct { - desc string - dbOpts *grocksdb.Options - cfOpts *grocksdb.Options - maxOpenFiles int - maxFileOpeningThreads int - writeBufferSize uint64 - numLevels int - }{ - { - desc: "default options", - dbOpts: dbOptsList[0], - cfOpts: cfOptsList[0], - maxOpenFiles: defaultOpts.GetMaxOpenFiles(), - maxFileOpeningThreads: defaultOpts.GetMaxFileOpeningThreads(), - writeBufferSize: defaultOpts.GetWriteBufferSize(), - numLevels: defaultOpts.GetNumLevels(), - }, - { - desc: "change 2 options", - dbOpts: dbOptsList[1], - cfOpts: cfOptsList[1], - maxOpenFiles: 999, - maxFileOpeningThreads: defaultOpts.GetMaxFileOpeningThreads(), - writeBufferSize: 999_999, - numLevels: defaultOpts.GetNumLevels(), - }, - { - desc: "change 4 options", - dbOpts: dbOptsList[2], - cfOpts: cfOptsList[2], - maxOpenFiles: 999, - maxFileOpeningThreads: 9, - writeBufferSize: 999_999, - numLevels: 9, - }, - } { - t.Run(tc.desc, func(t *testing.T) { - name := "application" - dir, err := os.MkdirTemp("", "rocksdb") - require.NoError(t, err) - defer func() { - err := os.RemoveAll(dir) - require.NoError(t, err) - }() - - db, err := newRocksDBWithOptions(name, dir, tc.dbOpts, tc.cfOpts, grocksdb.NewDefaultReadOptions(), true, defaultReportMetricsIntervalSecs) - require.NoError(t, err) - require.NoError(t, db.Close()) - - dbOpts, cfOpts, err := LoadLatestOptions(filepath.Join(dir, "application.db")) - require.NoError(t, err) - require.Equal(t, tc.maxOpenFiles, dbOpts.GetMaxOpenFiles()) - require.Equal(t, tc.maxFileOpeningThreads, dbOpts.GetMaxFileOpeningThreads()) - require.Equal(t, tc.writeBufferSize, cfOpts.GetWriteBufferSize()) - require.Equal(t, tc.numLevels, cfOpts.GetNumLevels()) - }) - } - }) - - t.Run("db doesn't exist yet", func(t *testing.T) { - defaultOpts := newDefaultOptions() - - dir, err := os.MkdirTemp("", "rocksdb") - require.NoError(t, err) - defer func() { - err := os.RemoveAll(dir) - require.NoError(t, err) - }() - - dbOpts, cfOpts, err := LoadLatestOptions(filepath.Join(dir, "application.db")) - require.NoError(t, err) - require.Equal(t, defaultOpts.GetMaxOpenFiles(), dbOpts.GetMaxOpenFiles()) - require.Equal(t, defaultOpts.GetMaxFileOpeningThreads(), dbOpts.GetMaxFileOpeningThreads()) - require.Equal(t, defaultOpts.GetWriteBufferSize(), cfOpts.GetWriteBufferSize()) - require.Equal(t, defaultOpts.GetNumLevels(), cfOpts.GetNumLevels()) - }) -} - -func TestOverrideDBOpts(t *testing.T) { - defaultOpts := newDefaultOptions() - - for _, tc := range []struct { - desc string - mockAppOptions *mockAppOptions - maxOpenFiles int - maxFileOpeningThreads int - }{ - { - desc: "override nothing", - mockAppOptions: newMockAppOptions(map[string]interface{}{}), - maxOpenFiles: defaultOpts.GetMaxOpenFiles(), - maxFileOpeningThreads: defaultOpts.GetMaxFileOpeningThreads(), - }, - { - desc: "override max-open-files", - mockAppOptions: newMockAppOptions(map[string]interface{}{ - maxOpenFilesDBOptName: 999, - }), - maxOpenFiles: 999, - maxFileOpeningThreads: defaultOpts.GetMaxFileOpeningThreads(), - }, - { - desc: "override max-file-opening-threads", - mockAppOptions: newMockAppOptions(map[string]interface{}{ - maxFileOpeningThreadsDBOptName: 9, - }), - maxOpenFiles: defaultOpts.GetMaxOpenFiles(), - maxFileOpeningThreads: 9, - }, - { - desc: "override max-open-files and max-file-opening-threads", - mockAppOptions: newMockAppOptions(map[string]interface{}{ - maxOpenFilesDBOptName: 999, - maxFileOpeningThreadsDBOptName: 9, - }), - maxOpenFiles: 999, - maxFileOpeningThreads: 9, - }, - } { - t.Run(tc.desc, func(t *testing.T) { - dbOpts := newDefaultOptions() - dbOpts = overrideDBOpts(dbOpts, tc.mockAppOptions) - - require.Equal(t, tc.maxOpenFiles, dbOpts.GetMaxOpenFiles()) - require.Equal(t, tc.maxFileOpeningThreads, dbOpts.GetMaxFileOpeningThreads()) - }) - } -} - -func TestOverrideCFOpts(t *testing.T) { - defaultOpts := newDefaultOptions() - - for _, tc := range []struct { - desc string - mockAppOptions *mockAppOptions - writeBufferSize uint64 - numLevels int - }{ - { - desc: "override nothing", - mockAppOptions: newMockAppOptions(map[string]interface{}{}), - writeBufferSize: defaultOpts.GetWriteBufferSize(), - numLevels: defaultOpts.GetNumLevels(), - }, - { - desc: "override write-buffer-size", - mockAppOptions: newMockAppOptions(map[string]interface{}{ - writeBufferSizeCFOptName: 999_999, - }), - writeBufferSize: 999_999, - numLevels: defaultOpts.GetNumLevels(), - }, - { - desc: "override num-levels", - mockAppOptions: newMockAppOptions(map[string]interface{}{ - numLevelsCFOptName: 9, - }), - writeBufferSize: defaultOpts.GetWriteBufferSize(), - numLevels: 9, - }, - { - desc: "override write-buffer-size and num-levels", - mockAppOptions: newMockAppOptions(map[string]interface{}{ - writeBufferSizeCFOptName: 999_999, - numLevelsCFOptName: 9, - }), - writeBufferSize: 999_999, - numLevels: 9, - }, - } { - t.Run(tc.desc, func(t *testing.T) { - cfOpts := newDefaultOptions() - cfOpts = overrideCFOpts(cfOpts, tc.mockAppOptions) - - require.Equal(t, tc.writeBufferSize, cfOpts.GetWriteBufferSize()) - require.Equal(t, tc.numLevels, cfOpts.GetNumLevels()) - }) - } -} - -func TestReadOptsFromAppOpts(t *testing.T) { - for _, tc := range []struct { - desc string - mockAppOptions *mockAppOptions - asyncIO bool - }{ - { - desc: "default options", - mockAppOptions: newMockAppOptions(map[string]interface{}{}), - asyncIO: false, - }, - { - desc: "set asyncIO option to true", - mockAppOptions: newMockAppOptions(map[string]interface{}{ - asyncIOReadOptName: true, - }), - asyncIO: true, - }, - } { - t.Run(tc.desc, func(t *testing.T) { - readOpts := readOptsFromAppOpts(tc.mockAppOptions) - - require.Equal(t, tc.asyncIO, readOpts.IsAsyncIO()) - }) - } -} - -func TestNewRocksDBWithOptions(t *testing.T) { - defaultOpts := newDefaultOptions() - - name := "application" - dir, err := os.MkdirTemp("", "rocksdb") - require.NoError(t, err) - defer func() { - err := os.RemoveAll(dir) - require.NoError(t, err) - }() - - dbOpts := newDefaultOptions() - dbOpts.SetMaxOpenFiles(999) - cfOpts := newDefaultOptions() - cfOpts.SetWriteBufferSize(999_999) - - db, err := newRocksDBWithOptions(name, dir, dbOpts, cfOpts, grocksdb.NewDefaultReadOptions(), true, defaultReportMetricsIntervalSecs) - require.NoError(t, err) - require.NoError(t, db.Close()) - - dbOpts, cfOpts, err = LoadLatestOptions(filepath.Join(dir, "application.db")) - require.NoError(t, err) - require.Equal(t, 999, dbOpts.GetMaxOpenFiles()) - require.Equal(t, defaultOpts.GetMaxFileOpeningThreads(), dbOpts.GetMaxFileOpeningThreads()) - require.Equal(t, uint64(999_999), cfOpts.GetWriteBufferSize()) - require.Equal(t, defaultOpts.GetNumLevels(), dbOpts.GetNumLevels()) -} - -func TestNewDefaultOptions(t *testing.T) { - defaultOpts := newDefaultOptions() - - maxOpenFiles := defaultOpts.GetMaxOpenFiles() - require.Equal(t, 4096, maxOpenFiles) -} diff --git a/cmd/opendb/props_loader.go b/cmd/opendb/props_loader.go deleted file mode 100644 index 16109b75..00000000 --- a/cmd/opendb/props_loader.go +++ /dev/null @@ -1,87 +0,0 @@ -//go:build rocksdb -// +build rocksdb - -package opendb - -import ( - "fmt" - "strings" - - "errors" -) - -type propsGetter interface { - GetProperty(propName string) (value string) - GetIntProperty(propName string) (value uint64, success bool) -} - -type propsLoader struct { - db propsGetter - errorMsgs []string -} - -func newPropsLoader(db propsGetter) *propsLoader { - return &propsLoader{ - db: db, - errorMsgs: make([]string, 0), - } -} - -func (l *propsLoader) load() (*properties, error) { - props := &properties{ - BaseLevel: l.getIntProperty("rocksdb.base-level"), - BlockCacheCapacity: l.getIntProperty("rocksdb.block-cache-capacity"), - BlockCachePinnedUsage: l.getIntProperty("rocksdb.block-cache-pinned-usage"), - BlockCacheUsage: l.getIntProperty("rocksdb.block-cache-usage"), - CurSizeActiveMemTable: l.getIntProperty("rocksdb.cur-size-active-mem-table"), - CurSizeAllMemTables: l.getIntProperty("rocksdb.cur-size-all-mem-tables"), - EstimateLiveDataSize: l.getIntProperty("rocksdb.estimate-live-data-size"), - EstimateNumKeys: l.getIntProperty("rocksdb.estimate-num-keys"), - EstimateTableReadersMem: l.getIntProperty("rocksdb.estimate-table-readers-mem"), - LiveSSTFilesSize: l.getIntProperty("rocksdb.live-sst-files-size"), - SizeAllMemTables: l.getIntProperty("rocksdb.size-all-mem-tables"), - OptionsStatistics: l.getProperty("rocksdb.options-statistics"), - } - - if len(l.errorMsgs) != 0 { - errorMsg := strings.Join(l.errorMsgs, ";") - return nil, errors.New(errorMsg) - } - - return props, nil -} - -func (l *propsLoader) getProperty(propName string) string { - value := l.db.GetProperty(propName) - if value == "" { - l.errorMsgs = append(l.errorMsgs, fmt.Sprintf("property %v is empty", propName)) - return "" - } - - return value -} - -func (l *propsLoader) getIntProperty(propName string) uint64 { - value, ok := l.db.GetIntProperty(propName) - if !ok { - l.errorMsgs = append(l.errorMsgs, fmt.Sprintf("can't get %v int property", propName)) - return 0 - } - - return value -} - -type properties struct { - BaseLevel uint64 - BlockCacheCapacity uint64 - BlockCachePinnedUsage uint64 - BlockCacheUsage uint64 - CurSizeActiveMemTable uint64 - CurSizeAllMemTables uint64 - EstimateLiveDataSize uint64 - EstimateNumKeys uint64 - EstimateTableReadersMem uint64 - LiveSSTFilesSize uint64 - SizeAllMemTables uint64 - OptionsStatistics string -} diff --git a/cmd/opendb/props_loader_test.go b/cmd/opendb/props_loader_test.go deleted file mode 100644 index 2643ab8b..00000000 --- a/cmd/opendb/props_loader_test.go +++ /dev/null @@ -1,112 +0,0 @@ -//go:build rocksdb -// +build rocksdb - -package opendb - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -type mockPropsGetter struct { - props map[string]string - intProps map[string]uint64 -} - -func newMockPropsGetter( - props map[string]string, - intProps map[string]uint64, -) *mockPropsGetter { - return &mockPropsGetter{ - props: props, - intProps: intProps, - } -} - -func (m *mockPropsGetter) GetProperty(propName string) string { - return m.props[propName] -} - -func (m *mockPropsGetter) GetIntProperty(propName string) (uint64, bool) { - prop, ok := m.intProps[propName] - return prop, ok -} - -func TestPropsLoader(t *testing.T) { - defaultProps := map[string]string{ - "rocksdb.options-statistics": "1", - } - defaultIntProps := map[string]uint64{ - "rocksdb.base-level": 1, - "rocksdb.block-cache-capacity": 2, - "rocksdb.block-cache-pinned-usage": 3, - "rocksdb.block-cache-usage": 4, - "rocksdb.cur-size-active-mem-table": 5, - "rocksdb.cur-size-all-mem-tables": 6, - "rocksdb.estimate-live-data-size": 7, - "rocksdb.estimate-num-keys": 8, - "rocksdb.estimate-table-readers-mem": 9, - "rocksdb.live-sst-files-size": 10, - "rocksdb.size-all-mem-tables": 11, - } - missingProps := make(map[string]string) - missingIntProps := make(map[string]uint64) - defaultExpectedProps := properties{ - BaseLevel: 1, - BlockCacheCapacity: 2, - BlockCachePinnedUsage: 3, - BlockCacheUsage: 4, - CurSizeActiveMemTable: 5, - CurSizeAllMemTables: 6, - EstimateLiveDataSize: 7, - EstimateNumKeys: 8, - EstimateTableReadersMem: 9, - LiveSSTFilesSize: 10, - SizeAllMemTables: 11, - OptionsStatistics: "1", - } - - for _, tc := range []struct { - desc string - props map[string]string - intProps map[string]uint64 - expectedProps *properties - success bool - }{ - { - desc: "success case", - props: defaultProps, - intProps: defaultIntProps, - expectedProps: &defaultExpectedProps, - success: true, - }, - { - desc: "missing props", - props: missingProps, - intProps: defaultIntProps, - expectedProps: nil, - success: false, - }, - { - desc: "missing integer props", - props: defaultProps, - intProps: missingIntProps, - expectedProps: nil, - success: false, - }, - } { - t.Run(tc.desc, func(t *testing.T) { - mockPropsGetter := newMockPropsGetter(tc.props, tc.intProps) - - propsLoader := newPropsLoader(mockPropsGetter) - actualProps, err := propsLoader.load() - if tc.success { - require.NoError(t, err) - } else { - require.Error(t, err) - } - require.Equal(t, tc.expectedProps, actualProps) - }) - } -} diff --git a/cmd/opendb/stat_parser.go b/cmd/opendb/stat_parser.go deleted file mode 100644 index 926d96c8..00000000 --- a/cmd/opendb/stat_parser.go +++ /dev/null @@ -1,111 +0,0 @@ -//go:build rocksdb -// +build rocksdb - -package opendb - -import ( - "fmt" - "strings" - - "errors" -) - -// stat represents one line from rocksdb statistics data, stat may have one or more properties -// examples: -// - rocksdb.block.cache.miss COUNT : 5 -// - rocksdb.compaction.times.micros P50 : 21112 P95 : 21112 P99 : 21112 P100 : 21112 COUNT : 1 SUM : 21112 -// `rocksdb.compaction.times.micros` is name of stat, P50, COUNT, SUM, etc... are props of stat -type stat struct { - name string - props map[string]string -} - -// parseSerializedStats parses serialisedStats into map of stat objects -// example of serializedStats: -// rocksdb.block.cache.miss COUNT : 5 -// rocksdb.compaction.times.micros P50 : 21112 P95 : 21112 P99 : 21112 P100 : 21112 COUNT : 1 SUM : 21112 -func parseSerializedStats(serializedStats string) (map[string]*stat, error) { - stats := make(map[string]*stat, 0) - - serializedStatList := strings.Split(serializedStats, "\n") - if len(serializedStatList) == 0 { - return nil, errors.New("serializedStats is empty") - } - serializedStatList = serializedStatList[:len(serializedStatList)-1] - // iterate over stats line by line - for _, serializedStat := range serializedStatList { - stat, err := parseSerializedStat(serializedStat) - if err != nil { - return nil, err - } - - stats[stat.name] = stat - } - - return stats, nil -} - -// parseSerializedStat parses serialisedStat into stat object -// example of serializedStat: -// rocksdb.block.cache.miss COUNT : 5 -func parseSerializedStat(serializedStat string) (*stat, error) { - tokens := strings.Split(serializedStat, " ") - tokensNum := len(tokens) - if err := validateTokens(tokens); err != nil { - return nil, fmt.Errorf("tokens are invalid: %v", err) - } - - props := make(map[string]string) - for idx := 1; idx < tokensNum; idx += 3 { - // never should happen, but double check to avoid unexpected panic - if idx+2 >= tokensNum { - break - } - - key := tokens[idx] - sep := tokens[idx+1] - value := tokens[idx+2] - - if err := validateStatProperty(key, value, sep); err != nil { - return nil, fmt.Errorf("invalid stat property: %v", err) - } - - props[key] = value - } - - return &stat{ - name: tokens[0], - props: props, - }, nil -} - -// validateTokens validates that tokens contains name + N triples (key, sep, value) -func validateTokens(tokens []string) error { - tokensNum := len(tokens) - if tokensNum < 4 { - return fmt.Errorf("invalid number of tokens: %v, tokens: %v", tokensNum, tokens) - } - if (tokensNum-1)%3 != 0 { - return fmt.Errorf("invalid number of tokens: %v, tokens: %v", tokensNum, tokens) - } - if tokens[0] == "" { - return fmt.Errorf("stat name shouldn't be empty") - } - - return nil -} - -// validateStatProperty validates that key and value are divided by separator and aren't empty -func validateStatProperty(key, value, sep string) error { - if key == "" { - return fmt.Errorf("key shouldn't be empty") - } - if sep != ":" { - return fmt.Errorf("separator should be :") - } - if value == "" { - return fmt.Errorf("value shouldn't be empty") - } - - return nil -} diff --git a/cmd/opendb/stat_parser_test.go b/cmd/opendb/stat_parser_test.go deleted file mode 100644 index dfeab9a4..00000000 --- a/cmd/opendb/stat_parser_test.go +++ /dev/null @@ -1,208 +0,0 @@ -//go:build rocksdb -// +build rocksdb - -package opendb - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestParseSerializedStats(t *testing.T) { - defaultSerializedStats := `rocksdb.block.cache.miss COUNT : 1 -rocksdb.block.cache.hit COUNT : 2 -rocksdb.block.cache.add COUNT : 3 -rocksdb.block.cache.add.failures COUNT : 4 -rocksdb.compaction.times.micros P50 : 1 P95 : 2 P99 : 3 P100 : 4 COUNT : 5 SUM : 6 -rocksdb.compaction.times.cpu_micros P50 : 7 P95 : 8 P99 : 9 P100 : 10 COUNT : 11 SUM : 12 -` - defaultExpectedStatMap := map[string]*stat{ - "rocksdb.block.cache.miss": { - name: "rocksdb.block.cache.miss", - props: map[string]string{ - "COUNT": "1", - }, - }, - "rocksdb.block.cache.hit": { - name: "rocksdb.block.cache.hit", - props: map[string]string{ - "COUNT": "2", - }, - }, - "rocksdb.block.cache.add": { - name: "rocksdb.block.cache.add", - props: map[string]string{ - "COUNT": "3", - }, - }, - "rocksdb.block.cache.add.failures": { - name: "rocksdb.block.cache.add.failures", - props: map[string]string{ - "COUNT": "4", - }, - }, - "rocksdb.compaction.times.micros": { - name: "rocksdb.compaction.times.micros", - props: map[string]string{ - "P50": "1", - "P95": "2", - "P99": "3", - "P100": "4", - "COUNT": "5", - "SUM": "6", - }, - }, - "rocksdb.compaction.times.cpu_micros": { - name: "rocksdb.compaction.times.cpu_micros", - props: map[string]string{ - "P50": "7", - "P95": "8", - "P99": "9", - "P100": "10", - "COUNT": "11", - "SUM": "12", - }, - }, - } - - for _, tc := range []struct { - desc string - serializedStats string - expectedStatMap map[string]*stat - errMsg string - }{ - { - desc: "success case", - serializedStats: defaultSerializedStats, - expectedStatMap: defaultExpectedStatMap, - errMsg: "", - }, - { - desc: "missing value #1", - serializedStats: `rocksdb.block.cache.miss COUNT : -`, - expectedStatMap: nil, - errMsg: "invalid number of tokens", - }, - { - desc: "missing value #2", - serializedStats: `rocksdb.compaction.times.micros P50 : 1 P95 : -`, - expectedStatMap: nil, - errMsg: "invalid number of tokens", - }, - { - desc: "missing stat name", - serializedStats: ` COUNT : 1 -`, - expectedStatMap: nil, - errMsg: "stat name shouldn't be empty", - }, - { - desc: "empty stat", - serializedStats: ``, - expectedStatMap: make(map[string]*stat), - errMsg: "", - }, - } { - t.Run(tc.desc, func(t *testing.T) { - actualStatMap, err := parseSerializedStats(tc.serializedStats) - if tc.errMsg == "" { - require.NoError(t, err) - } else { - require.Error(t, err) - require.Contains(t, err.Error(), tc.errMsg) - } - require.Equal(t, tc.expectedStatMap, actualStatMap) - }) - } -} - -func TestValidateTokens(t *testing.T) { - for _, tc := range []struct { - desc string - tokens []string - errMsg string - }{ - { - desc: "success case", - tokens: []string{"name", "key", ":", "value"}, - errMsg: "", - }, - { - desc: "missing value #1", - tokens: []string{"name", "key", ":"}, - errMsg: "invalid number of tokens", - }, - { - desc: "missing value #2", - tokens: []string{"name", "key", ":", "value", "key2", ":"}, - errMsg: "invalid number of tokens", - }, - { - desc: "empty stat name", - tokens: []string{"", "key", ":", "value"}, - errMsg: "stat name shouldn't be empty", - }, - } { - t.Run(tc.desc, func(t *testing.T) { - err := validateTokens(tc.tokens) - if tc.errMsg == "" { - require.NoError(t, err) - } else { - require.Error(t, err) - require.Contains(t, err.Error(), tc.errMsg) - } - }) - } -} - -func TestValidateStatProperty(t *testing.T) { - for _, tc := range []struct { - desc string - key string - value string - sep string - errMsg string - }{ - { - desc: "success case", - key: "key", - value: "value", - sep: ":", - errMsg: "", - }, - { - desc: "missing key", - key: "", - value: "value", - sep: ":", - errMsg: "key shouldn't be empty", - }, - { - desc: "missing value", - key: "key", - value: "", - sep: ":", - errMsg: "value shouldn't be empty", - }, - { - desc: "invalid separator", - key: "key", - value: "value", - sep: "#", - errMsg: "separator should be :", - }, - } { - t.Run(tc.desc, func(t *testing.T) { - err := validateStatProperty(tc.key, tc.value, tc.sep) - if tc.errMsg == "" { - require.NoError(t, err) - } else { - require.Error(t, err) - require.Contains(t, err.Error(), tc.errMsg) - } - }) - } -} diff --git a/cmd/opendb/stats_loader.go b/cmd/opendb/stats_loader.go deleted file mode 100644 index b378df76..00000000 --- a/cmd/opendb/stats_loader.go +++ /dev/null @@ -1,284 +0,0 @@ -//go:build rocksdb -// +build rocksdb - -package opendb - -import ( - "fmt" - "strconv" -) - -const ( - sum = "SUM" - count = "COUNT" - p50 = "P50" - p95 = "P95" - p99 = "P99" - p100 = "P100" -) - -type statLoader struct { - // statMap contains map of stat objects returned by parseSerializedStats function - // example of stats: - // #1: rocksdb.block.cache.miss COUNT : 5 - // #2: rocksdb.compaction.times.micros P50 : 21112 P95 : 21112 P99 : 21112 P100 : 21112 COUNT : 1 SUM : 21112 - // #1 case will be cast into int64 - // #2 case will be cast into float64Histogram - statMap map[string]*stat - - // NOTE: some methods accumulate errors instead of returning them, these methods are private and not intended to use outside - errors []error -} - -func newStatLoader(statMap map[string]*stat) *statLoader { - return &statLoader{ - statMap: statMap, - errors: make([]error, 0), - } -} - -type stats struct { - NumberKeysWritten int64 - NumberKeysRead int64 - NumberKeysUpdated int64 - - // total block cache misses - // BLOCK_CACHE_MISS == BLOCK_CACHE_INDEX_MISS + - // BLOCK_CACHE_FILTER_MISS + - // BLOCK_CACHE_DATA_MISS; - // BLOCK_CACHE_INDEX_MISS: # of times cache miss when accessing index block from block cache. - // BLOCK_CACHE_FILTER_MISS: # of times cache miss when accessing filter block from block cache. - // BLOCK_CACHE_DATA_MISS: # of times cache miss when accessing data block from block cache. - BlockCacheMiss int64 - - // total block cache hit - // BLOCK_CACHE_HIT == BLOCK_CACHE_INDEX_HIT + - // BLOCK_CACHE_FILTER_HIT + - // BLOCK_CACHE_DATA_HIT; - // BLOCK_CACHE_INDEX_HIT: # of times cache hit when accessing index block from block cache. - // BLOCK_CACHE_FILTER_HIT: # of times cache hit when accessing filter block from block cache. - // BLOCK_CACHE_DATA_HIT: # of times cache hit when accessing data block from block cache. - BlockCacheHit int64 - - // # of blocks added to block cache. - BlockCacheAdd int64 - // # of failures when adding blocks to block cache. - BlockCacheAddFailures int64 - - BlockCacheIndexMiss int64 - BlockCacheIndexHit int64 - BlockCacheIndexBytesInsert int64 - BlockCacheFilterMiss int64 - BlockCacheFilterHit int64 - BlockCacheFilterBytesInsert int64 - BlockCacheDataMiss int64 - BlockCacheDataHit int64 - BlockCacheDataBytesInsert int64 - - CompactReadBytes int64 // Bytes read during compaction - CompactWriteBytes int64 // Bytes written during compaction - - CompactionTimesMicros *float64Histogram - CompactionTimesCPUMicros *float64Histogram - NumFilesInSingleCompaction *float64Histogram - - // Read amplification statistics. - // Read amplification can be calculated using this formula - // (READ_AMP_TOTAL_READ_BYTES / READ_AMP_ESTIMATE_USEFUL_BYTES) - // - // REQUIRES: ReadOptions::read_amp_bytes_per_bit to be enabled - // TODO(yevhenii): seems not working? - ReadAmpEstimateUsefulBytes int64 // Estimate of total bytes actually used. - ReadAmpTotalReadBytes int64 // Total size of loaded data blocks. - - NumberFileOpens int64 - NumberFileErrors int64 - - // # of times bloom filter has avoided file reads, i.e., negatives. - BloomFilterUseful int64 - // # of times bloom FullFilter has not avoided the reads. - BloomFilterFullPositive int64 - // # of times bloom FullFilter has not avoided the reads and data actually - // exist. - BloomFilterFullTruePositive int64 - - // # of memtable hits. - MemtableHit int64 - // # of memtable misses. - MemtableMiss int64 - - // # of Get() queries served by L0 - GetHitL0 int64 - // # of Get() queries served by L1 - GetHitL1 int64 - // # of Get() queries served by L2 and up - GetHitL2AndUp int64 - - // The number of uncompressed bytes issued by DB::Put(), DB::Delete(), - // DB::Merge(), and DB::Write(). - BytesWritten int64 - // The number of uncompressed bytes read from DB::Get(). It could be - // either from memtables, cache, or table files. - // For the number of logical bytes read from DB::MultiGet(), - // please use NUMBER_MULTIGET_BYTES_READ. - BytesRead int64 - - // Writer has to wait for compaction or flush to finish. - StallMicros int64 - DBWriteStallHistogram *float64Histogram - - // Last level and non-last level read statistics - LastLevelReadBytes int64 - LastLevelReadCount int64 - NonLastLevelReadBytes int64 - NonLastLevelReadCount int64 - - DBGetMicros *float64Histogram - DBWriteMicros *float64Histogram - - // Value size distribution in each operation - BytesPerRead *float64Histogram - BytesPerWrite *float64Histogram - BytesPerMultiget *float64Histogram - - // Time spent flushing memtable to disk - FlushMicros *float64Histogram -} - -type float64Histogram struct { - Sum float64 - Count float64 - P50 float64 - P95 float64 - P99 float64 - P100 float64 -} - -func (l *statLoader) error() error { - if len(l.errors) != 0 { - return fmt.Errorf("%v", l.errors) - } - - return nil -} - -func (l *statLoader) load() (*stats, error) { - stats := &stats{ - NumberKeysWritten: l.getInt64StatValue("rocksdb.number.keys.written", count), - NumberKeysRead: l.getInt64StatValue("rocksdb.number.keys.read", count), - NumberKeysUpdated: l.getInt64StatValue("rocksdb.number.keys.updated", count), - BlockCacheMiss: l.getInt64StatValue("rocksdb.block.cache.miss", count), - BlockCacheHit: l.getInt64StatValue("rocksdb.block.cache.hit", count), - BlockCacheAdd: l.getInt64StatValue("rocksdb.block.cache.add", count), - BlockCacheAddFailures: l.getInt64StatValue("rocksdb.block.cache.add.failures", count), - BlockCacheIndexMiss: l.getInt64StatValue("rocksdb.block.cache.index.miss", count), - BlockCacheIndexHit: l.getInt64StatValue("rocksdb.block.cache.index.hit", count), - BlockCacheIndexBytesInsert: l.getInt64StatValue("rocksdb.block.cache.index.bytes.insert", count), - BlockCacheFilterMiss: l.getInt64StatValue("rocksdb.block.cache.filter.miss", count), - BlockCacheFilterHit: l.getInt64StatValue("rocksdb.block.cache.filter.hit", count), - BlockCacheFilterBytesInsert: l.getInt64StatValue("rocksdb.block.cache.filter.bytes.insert", count), - BlockCacheDataMiss: l.getInt64StatValue("rocksdb.block.cache.data.miss", count), - BlockCacheDataHit: l.getInt64StatValue("rocksdb.block.cache.data.hit", count), - BlockCacheDataBytesInsert: l.getInt64StatValue("rocksdb.block.cache.data.bytes.insert", count), - CompactReadBytes: l.getInt64StatValue("rocksdb.compact.read.bytes", count), - CompactWriteBytes: l.getInt64StatValue("rocksdb.compact.write.bytes", count), - CompactionTimesMicros: l.getFloat64HistogramStatValue("rocksdb.compaction.times.micros"), - CompactionTimesCPUMicros: l.getFloat64HistogramStatValue("rocksdb.compaction.times.cpu_micros"), - NumFilesInSingleCompaction: l.getFloat64HistogramStatValue("rocksdb.numfiles.in.singlecompaction"), - ReadAmpEstimateUsefulBytes: l.getInt64StatValue("rocksdb.read.amp.estimate.useful.bytes", count), - ReadAmpTotalReadBytes: l.getInt64StatValue("rocksdb.read.amp.total.read.bytes", count), - NumberFileOpens: l.getInt64StatValue("rocksdb.no.file.opens", count), - NumberFileErrors: l.getInt64StatValue("rocksdb.no.file.errors", count), - BloomFilterUseful: l.getInt64StatValue("rocksdb.bloom.filter.useful", count), - BloomFilterFullPositive: l.getInt64StatValue("rocksdb.bloom.filter.full.positive", count), - BloomFilterFullTruePositive: l.getInt64StatValue("rocksdb.bloom.filter.full.true.positive", count), - MemtableHit: l.getInt64StatValue("rocksdb.memtable.hit", count), - MemtableMiss: l.getInt64StatValue("rocksdb.memtable.miss", count), - GetHitL0: l.getInt64StatValue("rocksdb.l0.hit", count), - GetHitL1: l.getInt64StatValue("rocksdb.l1.hit", count), - GetHitL2AndUp: l.getInt64StatValue("rocksdb.l2andup.hit", count), - BytesWritten: l.getInt64StatValue("rocksdb.bytes.written", count), - BytesRead: l.getInt64StatValue("rocksdb.bytes.read", count), - StallMicros: l.getInt64StatValue("rocksdb.stall.micros", count), - DBWriteStallHistogram: l.getFloat64HistogramStatValue("rocksdb.db.write.stall"), - LastLevelReadBytes: l.getInt64StatValue("rocksdb.last.level.read.bytes", count), - LastLevelReadCount: l.getInt64StatValue("rocksdb.last.level.read.count", count), - NonLastLevelReadBytes: l.getInt64StatValue("rocksdb.non.last.level.read.bytes", count), - NonLastLevelReadCount: l.getInt64StatValue("rocksdb.non.last.level.read.count", count), - DBGetMicros: l.getFloat64HistogramStatValue("rocksdb.db.get.micros"), - DBWriteMicros: l.getFloat64HistogramStatValue("rocksdb.db.write.micros"), - BytesPerRead: l.getFloat64HistogramStatValue("rocksdb.bytes.per.read"), - BytesPerWrite: l.getFloat64HistogramStatValue("rocksdb.bytes.per.write"), - BytesPerMultiget: l.getFloat64HistogramStatValue("rocksdb.bytes.per.multiget"), - FlushMicros: l.getFloat64HistogramStatValue("rocksdb.db.flush.micros"), - } - - err := l.error() - if err != nil { - return nil, err - } - - return stats, nil -} - -// getFloat64HistogramStatValue converts stat object into float64Histogram -func (l *statLoader) getFloat64HistogramStatValue(statName string) *float64Histogram { - return &float64Histogram{ - Sum: l.getFloat64StatValue(statName, sum), - Count: l.getFloat64StatValue(statName, count), - P50: l.getFloat64StatValue(statName, p50), - P95: l.getFloat64StatValue(statName, p95), - P99: l.getFloat64StatValue(statName, p99), - P100: l.getFloat64StatValue(statName, p100), - } -} - -// getInt64StatValue converts property of stat object into int64 -func (l *statLoader) getInt64StatValue(statName, propName string) int64 { - stringVal := l.getStatValue(statName, propName) - if stringVal == "" { - l.errors = append(l.errors, fmt.Errorf("can't get stat by name: %v", statName)) - return 0 - } - - intVal, err := strconv.ParseInt(stringVal, 10, 64) - if err != nil { - l.errors = append(l.errors, fmt.Errorf("can't parse int: %v", err)) - return 0 - } - - return intVal -} - -// getFloat64StatValue converts property of stat object into float64 -func (l *statLoader) getFloat64StatValue(statName, propName string) float64 { - stringVal := l.getStatValue(statName, propName) - if stringVal == "" { - l.errors = append(l.errors, fmt.Errorf("can't get stat by name: %v", statName)) - return 0 - } - - floatVal, err := strconv.ParseFloat(stringVal, 64) - if err != nil { - l.errors = append(l.errors, fmt.Errorf("can't parse float: %v", err)) - return 0 - } - - return floatVal -} - -// getStatValue gets property of stat object -func (l *statLoader) getStatValue(statName, propName string) string { - stat, ok := l.statMap[statName] - if !ok { - l.errors = append(l.errors, fmt.Errorf("stat %v doesn't exist", statName)) - return "" - } - prop, ok := stat.props[propName] - if !ok { - l.errors = append(l.errors, fmt.Errorf("stat %v doesn't have %v property", statName, propName)) - return "" - } - - return prop -} diff --git a/cmd/opendb/stats_loader_test.go b/cmd/opendb/stats_loader_test.go deleted file mode 100644 index 81032ea1..00000000 --- a/cmd/opendb/stats_loader_test.go +++ /dev/null @@ -1,90 +0,0 @@ -//go:build rocksdb -// +build rocksdb - -package opendb - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestStatsLoader(t *testing.T) { - defaultStat := stat{ - props: map[string]string{ - "COUNT": "1", - }, - } - defaultHistogramStat := stat{ - props: map[string]string{ - "P50": "1", - "P95": "2", - "P99": "3", - "P100": "4", - "COUNT": "5", - "SUM": "6", - }, - } - defaultStatMap := map[string]*stat{ - "rocksdb.number.keys.written": &defaultStat, - "rocksdb.number.keys.read": &defaultStat, - "rocksdb.number.keys.updated": &defaultStat, - "rocksdb.block.cache.miss": &defaultStat, - "rocksdb.block.cache.hit": &defaultStat, - "rocksdb.block.cache.add": &defaultStat, - "rocksdb.block.cache.add.failures": &defaultStat, - "rocksdb.block.cache.index.miss": &defaultStat, - "rocksdb.block.cache.index.hit": &defaultStat, - "rocksdb.block.cache.index.bytes.insert": &defaultStat, - "rocksdb.block.cache.filter.miss": &defaultStat, - "rocksdb.block.cache.filter.hit": &defaultStat, - "rocksdb.block.cache.filter.bytes.insert": &defaultStat, - "rocksdb.block.cache.data.miss": &defaultStat, - "rocksdb.block.cache.data.hit": &defaultStat, - "rocksdb.block.cache.data.bytes.insert": &defaultStat, - "rocksdb.compact.read.bytes": &defaultStat, - "rocksdb.compact.write.bytes": &defaultStat, - "rocksdb.compaction.times.micros": &defaultHistogramStat, - "rocksdb.compaction.times.cpu_micros": &defaultHistogramStat, - "rocksdb.numfiles.in.singlecompaction": &defaultHistogramStat, - "rocksdb.read.amp.estimate.useful.bytes": &defaultStat, - "rocksdb.read.amp.total.read.bytes": &defaultStat, - "rocksdb.no.file.opens": &defaultStat, - "rocksdb.no.file.errors": &defaultStat, - "rocksdb.bloom.filter.useful": &defaultStat, - "rocksdb.bloom.filter.full.positive": &defaultStat, - "rocksdb.bloom.filter.full.true.positive": &defaultStat, - "rocksdb.memtable.hit": &defaultStat, - "rocksdb.memtable.miss": &defaultStat, - "rocksdb.l0.hit": &defaultStat, - "rocksdb.l1.hit": &defaultStat, - "rocksdb.l2andup.hit": &defaultStat, - "rocksdb.bytes.written": &defaultStat, - "rocksdb.bytes.read": &defaultStat, - "rocksdb.stall.micros": &defaultStat, - "rocksdb.db.write.stall": &defaultHistogramStat, - "rocksdb.last.level.read.bytes": &defaultStat, - "rocksdb.last.level.read.count": &defaultStat, - "rocksdb.non.last.level.read.bytes": &defaultStat, - "rocksdb.non.last.level.read.count": &defaultStat, - "rocksdb.db.get.micros": &defaultHistogramStat, - "rocksdb.db.write.micros": &defaultHistogramStat, - "rocksdb.bytes.per.read": &defaultHistogramStat, - "rocksdb.bytes.per.write": &defaultHistogramStat, - "rocksdb.bytes.per.multiget": &defaultHistogramStat, - "rocksdb.db.flush.micros": &defaultHistogramStat, - } - - statLoader := newStatLoader(defaultStatMap) - stats, err := statLoader.load() - require.NoError(t, err) - - require.Equal(t, stats.NumberKeysWritten, int64(1)) - require.Equal(t, stats.NumberKeysRead, int64(1)) - require.Equal(t, stats.CompactionTimesMicros.P50, float64(1)) - require.Equal(t, stats.CompactionTimesMicros.P95, float64(2)) - require.Equal(t, stats.CompactionTimesMicros.P99, float64(3)) - require.Equal(t, stats.CompactionTimesMicros.P100, float64(4)) - require.Equal(t, stats.CompactionTimesMicros.Count, float64(5)) - require.Equal(t, stats.CompactionTimesMicros.Sum, float64(6)) -} diff --git a/contracts/package-lock.json b/contracts/package-lock.json index 1af6533e..fa3054a8 100644 --- a/contracts/package-lock.json +++ b/contracts/package-lock.json @@ -8,23 +8,31 @@ "name": "0g-chain-contracts", "version": "0.0.1", "devDependencies": { - "@nomicfoundation/hardhat-toolbox": "^2.0.2", + "@nomicfoundation/hardhat-toolbox": "^5.0.0", "@openzeppelin/contracts": "4.8.3", "@typescript-eslint/eslint-plugin": "^5.59.6", "@typescript-eslint/parser": "^5.59.6", "eslint": "^8.40.0", "eslint-config-prettier": "8.8.0", "eslint-plugin-prettier": "^4.2.1", - "hardhat": "^2.14.0", + "hardhat": "^2.22.8", "prettier": "2.8.8", "prettier-plugin-solidity": "^1.1.3", "solhint": "^3.4.1", "typescript": "^5.0.4" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, + "node_modules/@adraffy/ens-normalize": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", + "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/@babel/code-frame": { "version": "7.21.4", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", @@ -60,32 +68,6 @@ "node": ">=6.9.0" } }, - "node_modules/@chainsafe/as-sha256": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@chainsafe/as-sha256/-/as-sha256-0.3.1.tgz", - "integrity": "sha512-hldFFYuf49ed7DAakWVXSJODuq3pzJEguD8tQ7h+sGkM18vja+OFoJI9krnGmgzyuZC2ETX0NOIcCTy31v2Mtg==", - "dev": true - }, - "node_modules/@chainsafe/persistent-merkle-tree": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.4.2.tgz", - "integrity": "sha512-lLO3ihKPngXLTus/L7WHKaw9PnNJWizlOF1H9NNzHP6Xvh82vzg9F2bzkXhYIFshMZ2gTCEz8tq6STe7r5NDfQ==", - "dev": true, - "dependencies": { - "@chainsafe/as-sha256": "^0.3.1" - } - }, - "node_modules/@chainsafe/ssz": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@chainsafe/ssz/-/ssz-0.9.4.tgz", - "integrity": "sha512-77Qtg2N1ayqs4Bg/wvnWfg5Bta7iy7IRh8XqXh7oNMeP2HBbBwx8m6yTpA8p0EHItWPEBkgZd5S5/LSlp3GXuQ==", - "dev": true, - "dependencies": { - "@chainsafe/as-sha256": "^0.3.1", - "@chainsafe/persistent-merkle-tree": "^0.4.2", - "case": "^1.6.3" - } - }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", @@ -272,26 +254,6 @@ "@ethersproject/bytes": "^5.7.0" } }, - "node_modules/@ethersproject/basex": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.7.0.tgz", - "integrity": "sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/properties": "^5.7.0" - } - }, "node_modules/@ethersproject/bignumber": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz", @@ -351,34 +313,6 @@ "@ethersproject/bignumber": "^5.7.0" } }, - "node_modules/@ethersproject/contracts": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.7.0.tgz", - "integrity": "sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abi": "^5.7.0", - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/transactions": "^5.7.0" - } - }, "node_modules/@ethersproject/hash": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz", @@ -406,67 +340,6 @@ "@ethersproject/strings": "^5.7.0" } }, - "node_modules/@ethersproject/hdnode": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.7.0.tgz", - "integrity": "sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/basex": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/pbkdf2": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/sha2": "^5.7.0", - "@ethersproject/signing-key": "^5.7.0", - "@ethersproject/strings": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/wordlists": "^5.7.0" - } - }, - "node_modules/@ethersproject/json-wallets": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz", - "integrity": "sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/hdnode": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/pbkdf2": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/random": "^5.7.0", - "@ethersproject/strings": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "aes-js": "3.0.0", - "scrypt-js": "3.0.1" - } - }, "node_modules/@ethersproject/keccak256": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz", @@ -522,26 +395,6 @@ "@ethersproject/logger": "^5.7.0" } }, - "node_modules/@ethersproject/pbkdf2": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz", - "integrity": "sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/sha2": "^5.7.0" - } - }, "node_modules/@ethersproject/properties": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz", @@ -561,85 +414,6 @@ "@ethersproject/logger": "^5.7.0" } }, - "node_modules/@ethersproject/providers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.7.2.tgz", - "integrity": "sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/base64": "^5.7.0", - "@ethersproject/basex": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/networks": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/random": "^5.7.0", - "@ethersproject/rlp": "^5.7.0", - "@ethersproject/sha2": "^5.7.0", - "@ethersproject/strings": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/web": "^5.7.0", - "bech32": "1.1.4", - "ws": "7.4.6" - } - }, - "node_modules/@ethersproject/providers/node_modules/ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", - "dev": true, - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/@ethersproject/random": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.7.0.tgz", - "integrity": "sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, "node_modules/@ethersproject/rlp": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz", @@ -660,27 +434,6 @@ "@ethersproject/logger": "^5.7.0" } }, - "node_modules/@ethersproject/sha2": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.7.0.tgz", - "integrity": "sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "hash.js": "1.1.7" - } - }, "node_modules/@ethersproject/signing-key": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz", @@ -705,30 +458,6 @@ "hash.js": "1.1.7" } }, - "node_modules/@ethersproject/solidity": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.7.0.tgz", - "integrity": "sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/sha2": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, "node_modules/@ethersproject/strings": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz", @@ -777,60 +506,6 @@ "@ethersproject/signing-key": "^5.7.0" } }, - "node_modules/@ethersproject/units": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.7.0.tgz", - "integrity": "sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/wallet": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.7.0.tgz", - "integrity": "sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/hdnode": "^5.7.0", - "@ethersproject/json-wallets": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/random": "^5.7.0", - "@ethersproject/signing-key": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/wordlists": "^5.7.0" - } - }, "node_modules/@ethersproject/web": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz", @@ -854,27 +529,13 @@ "@ethersproject/strings": "^5.7.0" } }, - "node_modules/@ethersproject/wordlists": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.7.0.tgz", - "integrity": "sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==", + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" + "engines": { + "node": ">=14" } }, "node_modules/@humanwhocodes/config-array": { @@ -954,38 +615,32 @@ "node": ">=12.0.0" } }, - "node_modules/@morgan-stanley/ts-mocking-bird": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/@morgan-stanley/ts-mocking-bird/-/ts-mocking-bird-0.6.4.tgz", - "integrity": "sha512-57VJIflP8eR2xXa9cD1LUawh+Gh+BVQfVu0n6GALyg/AqV/Nz25kDRvws3i9kIe1PTrbsZZOYpsYp6bXPd6nVA==", + "node_modules/@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { - "lodash": "^4.17.16", - "uuid": "^7.0.3" + "@noble/hashes": "1.3.2" }, - "peerDependencies": { - "jasmine": "2.x || 3.x || 4.x", - "jest": "26.x || 27.x || 28.x", - "typescript": ">=4.2" - }, - "peerDependenciesMeta": { - "jasmine": { - "optional": true - }, - "jest": { - "optional": true - } + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@morgan-stanley/ts-mocking-bird/node_modules/uuid": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", - "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", + "node_modules/@noble/curves/node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", "dev": true, + "license": "MIT", "peer": true, - "bin": { - "uuid": "dist/bin/uuid" + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, "node_modules/@noble/hashes": { @@ -1047,289 +702,140 @@ "node": ">= 8" } }, - "node_modules/@nomicfoundation/ethereumjs-block": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-5.0.1.tgz", - "integrity": "sha512-u1Yioemi6Ckj3xspygu/SfFvm8vZEO8/Yx5a1QLzi6nVU0jz3Pg2OmHKJ5w+D9Ogk1vhwRiqEBAqcb0GVhCyHw==", + "node_modules/@nomicfoundation/edr": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.5.2.tgz", + "integrity": "sha512-hW/iLvUQZNTVjFyX/I40rtKvvDOqUEyIi96T28YaLfmPL+3LW2lxmYLUXEJ6MI14HzqxDqrLyhf6IbjAa2r3Dw==", "dev": true, + "license": "MIT", "dependencies": { - "@nomicfoundation/ethereumjs-common": "4.0.1", - "@nomicfoundation/ethereumjs-rlp": "5.0.1", - "@nomicfoundation/ethereumjs-trie": "6.0.1", - "@nomicfoundation/ethereumjs-tx": "5.0.1", - "@nomicfoundation/ethereumjs-util": "9.0.1", - "ethereum-cryptography": "0.1.3", - "ethers": "^5.7.1" + "@nomicfoundation/edr-darwin-arm64": "0.5.2", + "@nomicfoundation/edr-darwin-x64": "0.5.2", + "@nomicfoundation/edr-linux-arm64-gnu": "0.5.2", + "@nomicfoundation/edr-linux-arm64-musl": "0.5.2", + "@nomicfoundation/edr-linux-x64-gnu": "0.5.2", + "@nomicfoundation/edr-linux-x64-musl": "0.5.2", + "@nomicfoundation/edr-win32-x64-msvc": "0.5.2" }, "engines": { - "node": ">=14" + "node": ">= 18" } }, - "node_modules/@nomicfoundation/ethereumjs-block/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "node_modules/@nomicfoundation/edr-darwin-arm64": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.5.2.tgz", + "integrity": "sha512-Gm4wOPKhbDjGTIRyFA2QUAPfCXA1AHxYOKt3yLSGJkQkdy9a5WW+qtqKeEKHc/+4wpJSLtsGQfpzyIzggFfo/A==", "dev": true, - "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" - } - }, - "node_modules/@nomicfoundation/ethereumjs-blockchain": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-7.0.1.tgz", - "integrity": "sha512-NhzndlGg829XXbqJEYrF1VeZhAwSPgsK/OB7TVrdzft3y918hW5KNd7gIZ85sn6peDZOdjBsAXIpXZ38oBYE5A==", - "dev": true, - "dependencies": { - "@nomicfoundation/ethereumjs-block": "5.0.1", - "@nomicfoundation/ethereumjs-common": "4.0.1", - "@nomicfoundation/ethereumjs-ethash": "3.0.1", - "@nomicfoundation/ethereumjs-rlp": "5.0.1", - "@nomicfoundation/ethereumjs-trie": "6.0.1", - "@nomicfoundation/ethereumjs-tx": "5.0.1", - "@nomicfoundation/ethereumjs-util": "9.0.1", - "abstract-level": "^1.0.3", - "debug": "^4.3.3", - "ethereum-cryptography": "0.1.3", - "level": "^8.0.0", - "lru-cache": "^5.1.1", - "memory-level": "^1.0.0" - }, + "license": "MIT", "engines": { - "node": ">=14" + "node": ">= 18" } }, - "node_modules/@nomicfoundation/ethereumjs-blockchain/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "node_modules/@nomicfoundation/edr-darwin-x64": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.5.2.tgz", + "integrity": "sha512-ClyABq2dFCsrYEED3/UIO0c7p4H1/4vvlswFlqUyBpOkJccr75qIYvahOSJRM62WgUFRhbSS0OJXFRwc/PwmVg==", "dev": true, - "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@nomicfoundation/edr-linux-arm64-gnu": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.5.2.tgz", + "integrity": "sha512-HWMTVk1iOabfvU2RvrKLDgtFjJZTC42CpHiw2h6rfpsgRqMahvIlx2jdjWYzFNy1jZKPTN1AStQ/91MRrg5KnA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@nomicfoundation/edr-linux-arm64-musl": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.5.2.tgz", + "integrity": "sha512-CwsQ10xFx/QAD5y3/g5alm9+jFVuhc7uYMhrZAu9UVF+KtVjeCvafj0PaVsZ8qyijjqVuVsJ8hD1x5ob7SMcGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@nomicfoundation/edr-linux-x64-gnu": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.5.2.tgz", + "integrity": "sha512-CWVCEdhWJ3fmUpzWHCRnC0/VLBDbqtqTGTR6yyY1Ep3S3BOrHEAvt7h5gx85r2vLcztisu2vlDq51auie4IU1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@nomicfoundation/edr-linux-x64-musl": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.5.2.tgz", + "integrity": "sha512-+aJDfwhkddy2pP5u1ISg3IZVAm0dO836tRlDTFWtvvSMQ5hRGqPcWwlsbobhDQsIxhPJyT7phL0orCg5W3WMeA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@nomicfoundation/edr-win32-x64-msvc": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.5.2.tgz", + "integrity": "sha512-CcvvuA3sAv7liFNPsIR/68YlH6rrybKzYttLlMr80d4GKJjwJ5OKb3YgE6FdZZnOfP19HEHhsLcE0DPLtY3r0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18" } }, "node_modules/@nomicfoundation/ethereumjs-common": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.1.tgz", - "integrity": "sha512-OBErlkfp54GpeiE06brBW/TTbtbuBJV5YI5Nz/aB2evTDo+KawyEzPjBlSr84z/8MFfj8wS2wxzQX1o32cev5g==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.4.tgz", + "integrity": "sha512-9Rgb658lcWsjiicr5GzNCjI1llow/7r0k50dLL95OJ+6iZJcVbi15r3Y0xh2cIO+zgX0WIHcbzIu6FeQf9KPrg==", "dev": true, + "license": "MIT", "dependencies": { - "@nomicfoundation/ethereumjs-util": "9.0.1", - "crc-32": "^1.2.0" - } - }, - "node_modules/@nomicfoundation/ethereumjs-ethash": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-3.0.1.tgz", - "integrity": "sha512-KDjGIB5igzWOp8Ik5I6QiRH5DH+XgILlplsHR7TEuWANZA759G6krQ6o8bvj+tRUz08YygMQu/sGd9mJ1DYT8w==", - "dev": true, - "dependencies": { - "@nomicfoundation/ethereumjs-block": "5.0.1", - "@nomicfoundation/ethereumjs-rlp": "5.0.1", - "@nomicfoundation/ethereumjs-util": "9.0.1", - "abstract-level": "^1.0.3", - "bigint-crypto-utils": "^3.0.23", - "ethereum-cryptography": "0.1.3" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@nomicfoundation/ethereumjs-ethash/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "dev": true, - "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" - } - }, - "node_modules/@nomicfoundation/ethereumjs-evm": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-2.0.1.tgz", - "integrity": "sha512-oL8vJcnk0Bx/onl+TgQOQ1t/534GKFaEG17fZmwtPFeH8S5soiBYPCLUrvANOl4sCp9elYxIMzIiTtMtNNN8EQ==", - "dev": true, - "dependencies": { - "@ethersproject/providers": "^5.7.1", - "@nomicfoundation/ethereumjs-common": "4.0.1", - "@nomicfoundation/ethereumjs-tx": "5.0.1", - "@nomicfoundation/ethereumjs-util": "9.0.1", - "debug": "^4.3.3", - "ethereum-cryptography": "0.1.3", - "mcl-wasm": "^0.7.1", - "rustbn.js": "~0.2.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@nomicfoundation/ethereumjs-evm/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "dev": true, - "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" + "@nomicfoundation/ethereumjs-util": "9.0.4" } }, "node_modules/@nomicfoundation/ethereumjs-rlp": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.1.tgz", - "integrity": "sha512-xtxrMGa8kP4zF5ApBQBtjlSbN5E2HI8m8FYgVSYAnO6ssUoY5pVPGy2H8+xdf/bmMa22Ce8nWMH3aEW8CcqMeQ==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.4.tgz", + "integrity": "sha512-8H1S3s8F6QueOc/X92SdrA4RDenpiAEqMg5vJH99kcQaCy/a3Q6fgseo75mgWlbanGJXSlAPtnCeG9jvfTYXlw==", "dev": true, + "license": "MPL-2.0", "bin": { - "rlp": "bin/rlp" + "rlp": "bin/rlp.cjs" }, "engines": { - "node": ">=14" - } - }, - "node_modules/@nomicfoundation/ethereumjs-statemanager": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-2.0.1.tgz", - "integrity": "sha512-B5ApMOnlruVOR7gisBaYwFX+L/AP7i/2oAahatssjPIBVDF6wTX1K7Qpa39E/nzsH8iYuL3krkYeUFIdO3EMUQ==", - "dev": true, - "dependencies": { - "@nomicfoundation/ethereumjs-common": "4.0.1", - "@nomicfoundation/ethereumjs-rlp": "5.0.1", - "debug": "^4.3.3", - "ethereum-cryptography": "0.1.3", - "ethers": "^5.7.1", - "js-sdsl": "^4.1.4" - } - }, - "node_modules/@nomicfoundation/ethereumjs-statemanager/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "dev": true, - "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" - } - }, - "node_modules/@nomicfoundation/ethereumjs-trie": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-6.0.1.tgz", - "integrity": "sha512-A64It/IMpDVODzCgxDgAAla8jNjNtsoQZIzZUfIV5AY6Coi4nvn7+VReBn5itlxMiL2yaTlQr9TRWp3CSI6VoA==", - "dev": true, - "dependencies": { - "@nomicfoundation/ethereumjs-rlp": "5.0.1", - "@nomicfoundation/ethereumjs-util": "9.0.1", - "@types/readable-stream": "^2.3.13", - "ethereum-cryptography": "0.1.3", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@nomicfoundation/ethereumjs-trie/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "dev": true, - "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" + "node": ">=18" } }, "node_modules/@nomicfoundation/ethereumjs-tx": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.1.tgz", - "integrity": "sha512-0HwxUF2u2hrsIM1fsasjXvlbDOq1ZHFV2dd1yGq8CA+MEYhaxZr8OTScpVkkxqMwBcc5y83FyPl0J9MZn3kY0w==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.4.tgz", + "integrity": "sha512-Xjv8wAKJGMrP1f0n2PeyfFCCojHd7iS3s/Ab7qzF1S64kxZ8Z22LCMynArYsVqiFx6rzYy548HNVEyI+AYN/kw==", "dev": true, + "license": "MPL-2.0", "dependencies": { - "@chainsafe/ssz": "^0.9.2", - "@ethersproject/providers": "^5.7.2", - "@nomicfoundation/ethereumjs-common": "4.0.1", - "@nomicfoundation/ethereumjs-rlp": "5.0.1", - "@nomicfoundation/ethereumjs-util": "9.0.1", + "@nomicfoundation/ethereumjs-common": "4.0.4", + "@nomicfoundation/ethereumjs-rlp": "5.0.4", + "@nomicfoundation/ethereumjs-util": "9.0.4", "ethereum-cryptography": "0.1.3" }, "engines": { - "node": ">=14" + "node": ">=18" + }, + "peerDependencies": { + "c-kzg": "^2.1.2" + }, + "peerDependenciesMeta": { + "c-kzg": { + "optional": true + } } }, "node_modules/@nomicfoundation/ethereumjs-tx/node_modules/ethereum-cryptography": { @@ -1337,6 +843,7 @@ "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/pbkdf2": "^3.0.0", "@types/secp256k1": "^4.0.1", @@ -1356,36 +863,25 @@ } }, "node_modules/@nomicfoundation/ethereumjs-util": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.1.tgz", - "integrity": "sha512-TwbhOWQ8QoSCFhV/DDfSmyfFIHjPjFBj957219+V3jTZYZ2rf9PmDtNOeZWAE3p3vlp8xb02XGpd0v6nTUPbsA==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.4.tgz", + "integrity": "sha512-sLOzjnSrlx9Bb9EFNtHzK/FJFsfg2re6bsGqinFinH1gCqVfz9YYlXiMWwDM4C/L4ywuHFCYwfKTVr/QHQcU0Q==", "dev": true, + "license": "MPL-2.0", "dependencies": { - "@chainsafe/ssz": "^0.10.0", - "@nomicfoundation/ethereumjs-rlp": "5.0.1", + "@nomicfoundation/ethereumjs-rlp": "5.0.4", "ethereum-cryptography": "0.1.3" }, "engines": { - "node": ">=14" - } - }, - "node_modules/@nomicfoundation/ethereumjs-util/node_modules/@chainsafe/persistent-merkle-tree": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.5.0.tgz", - "integrity": "sha512-l0V1b5clxA3iwQLXP40zYjyZYospQLZXzBVIhhr9kDg/1qHZfzzHw0jj4VPBijfYCArZDlPkRi1wZaV2POKeuw==", - "dev": true, - "dependencies": { - "@chainsafe/as-sha256": "^0.3.1" - } - }, - "node_modules/@nomicfoundation/ethereumjs-util/node_modules/@chainsafe/ssz": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/@chainsafe/ssz/-/ssz-0.10.2.tgz", - "integrity": "sha512-/NL3Lh8K+0q7A3LsiFq09YXS9fPE+ead2rr7vM2QK8PLzrNsw3uqrif9bpRX5UxgeRjM+vYi+boCM3+GM4ovXg==", - "dev": true, - "dependencies": { - "@chainsafe/as-sha256": "^0.3.1", - "@chainsafe/persistent-merkle-tree": "^0.5.0" + "node": ">=18" + }, + "peerDependencies": { + "c-kzg": "^2.1.2" + }, + "peerDependenciesMeta": { + "c-kzg": { + "optional": true + } } }, "node_modules/@nomicfoundation/ethereumjs-util/node_modules/ethereum-cryptography": { @@ -1393,53 +889,7 @@ "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", "dev": true, - "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" - } - }, - "node_modules/@nomicfoundation/ethereumjs-vm": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-7.0.1.tgz", - "integrity": "sha512-rArhyn0jPsS/D+ApFsz3yVJMQ29+pVzNZ0VJgkzAZ+7FqXSRtThl1C1prhmlVr3YNUlfpZ69Ak+RUT4g7VoOuQ==", - "dev": true, - "dependencies": { - "@nomicfoundation/ethereumjs-block": "5.0.1", - "@nomicfoundation/ethereumjs-blockchain": "7.0.1", - "@nomicfoundation/ethereumjs-common": "4.0.1", - "@nomicfoundation/ethereumjs-evm": "2.0.1", - "@nomicfoundation/ethereumjs-rlp": "5.0.1", - "@nomicfoundation/ethereumjs-statemanager": "2.0.1", - "@nomicfoundation/ethereumjs-trie": "6.0.1", - "@nomicfoundation/ethereumjs-tx": "5.0.1", - "@nomicfoundation/ethereumjs-util": "9.0.1", - "debug": "^4.3.3", - "ethereum-cryptography": "0.1.3", - "mcl-wasm": "^0.7.1", - "rustbn.js": "~0.2.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@nomicfoundation/ethereumjs-vm/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "dev": true, + "license": "MIT", "dependencies": { "@types/pbkdf2": "^3.0.0", "@types/secp256k1": "^4.0.1", @@ -1459,25 +909,199 @@ } }, "node_modules/@nomicfoundation/hardhat-chai-matchers": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-chai-matchers/-/hardhat-chai-matchers-1.0.6.tgz", - "integrity": "sha512-f5ZMNmabZeZegEfuxn/0kW+mm7+yV7VNDxLpMOMGXWFJ2l/Ct3QShujzDRF9cOkK9Ui/hbDeOWGZqyQALDXVCQ==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-chai-matchers/-/hardhat-chai-matchers-2.0.7.tgz", + "integrity": "sha512-RQfsiTwdf0SP+DtuNYvm4921X6VirCQq0Xyh+mnuGlTwEFSPZ/o27oQC+l+3Y/l48DDU7+ZcYBR+Fp+Rp94LfQ==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { - "@ethersproject/abi": "^5.1.2", "@types/chai-as-promised": "^7.1.3", "chai-as-promised": "^7.1.1", "deep-eql": "^4.0.1", "ordinal": "^1.0.3" }, "peerDependencies": { - "@nomiclabs/hardhat-ethers": "^2.0.0", + "@nomicfoundation/hardhat-ethers": "^3.0.0", "chai": "^4.2.0", - "ethers": "^5.0.0", + "ethers": "^6.1.0", "hardhat": "^2.9.4" } }, + "node_modules/@nomicfoundation/hardhat-ethers": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ethers/-/hardhat-ethers-3.0.6.tgz", + "integrity": "sha512-/xzkFQAaHQhmIAYOQmvHBPwL+NkwLzT9gRZBsgWUYeV+E6pzXsBQsHfRYbAZ3XEYare+T7S+5Tg/1KDJgepSkA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "debug": "^4.1.1", + "lodash.isequal": "^4.5.0" + }, + "peerDependencies": { + "ethers": "^6.1.0", + "hardhat": "^2.0.0" + } + }, + "node_modules/@nomicfoundation/hardhat-ignition": { + "version": "0.15.5", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ignition/-/hardhat-ignition-0.15.5.tgz", + "integrity": "sha512-Y5nhFXFqt4owA6Ooag8ZBFDF2RAZElMXViknVIsi3m45pbQimS50ti6FU8HxfRkDnBARa40CIn7UGV0hrelzDw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@nomicfoundation/ignition-core": "^0.15.5", + "@nomicfoundation/ignition-ui": "^0.15.5", + "chalk": "^4.0.0", + "debug": "^4.3.2", + "fs-extra": "^10.0.0", + "prompts": "^2.4.2" + }, + "peerDependencies": { + "@nomicfoundation/hardhat-verify": "^2.0.1", + "hardhat": "^2.18.0" + } + }, + "node_modules/@nomicfoundation/hardhat-ignition-ethers": { + "version": "0.15.5", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ignition-ethers/-/hardhat-ignition-ethers-0.15.5.tgz", + "integrity": "sha512-W6s1QN9CFxzSVZS6w9Jcj3WLaK32z2FP5MxNU2OKY1Fn9ZzLr+miXbUbWYuRHl6dxrrl6sE8cv33Cybv19pmCg==", + "dev": true, + "license": "MIT", + "peer": true, + "peerDependencies": { + "@nomicfoundation/hardhat-ethers": "^3.0.4", + "@nomicfoundation/hardhat-ignition": "^0.15.5", + "@nomicfoundation/ignition-core": "^0.15.5", + "ethers": "^6.7.0", + "hardhat": "^2.18.0" + } + }, + "node_modules/@nomicfoundation/hardhat-ignition/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@nomicfoundation/hardhat-ignition/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@nomicfoundation/hardhat-ignition/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@nomicfoundation/hardhat-ignition/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@nomicfoundation/hardhat-ignition/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@nomicfoundation/hardhat-ignition/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@nomicfoundation/hardhat-ignition/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@nomicfoundation/hardhat-ignition/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@nomicfoundation/hardhat-ignition/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/@nomicfoundation/hardhat-network-helpers": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-network-helpers/-/hardhat-network-helpers-1.0.8.tgz", @@ -1533,32 +1157,160 @@ } }, "node_modules/@nomicfoundation/hardhat-toolbox": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-toolbox/-/hardhat-toolbox-2.0.2.tgz", - "integrity": "sha512-vnN1AzxbvpSx9pfdRHbUzTRIXpMLPXnUlkW855VaDk6N1pwRaQ2gNzEmFAABk4lWf11E00PKwFd/q27HuwYrYg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-toolbox/-/hardhat-toolbox-5.0.0.tgz", + "integrity": "sha512-FnUtUC5PsakCbwiVNsqlXVIWG5JIb5CEZoSXbJUsEBun22Bivx2jhF1/q9iQbzuaGpJKFQyOhemPB2+XlEE6pQ==", "dev": true, + "license": "MIT", "peerDependencies": { - "@ethersproject/abi": "^5.4.7", - "@ethersproject/providers": "^5.4.7", - "@nomicfoundation/hardhat-chai-matchers": "^1.0.0", + "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", + "@nomicfoundation/hardhat-ethers": "^3.0.0", + "@nomicfoundation/hardhat-ignition-ethers": "^0.15.0", "@nomicfoundation/hardhat-network-helpers": "^1.0.0", - "@nomiclabs/hardhat-ethers": "^2.0.0", - "@nomiclabs/hardhat-etherscan": "^3.0.0", - "@typechain/ethers-v5": "^10.1.0", - "@typechain/hardhat": "^6.1.2", + "@nomicfoundation/hardhat-verify": "^2.0.0", + "@typechain/ethers-v6": "^0.5.0", + "@typechain/hardhat": "^9.0.0", "@types/chai": "^4.2.0", "@types/mocha": ">=9.1.0", - "@types/node": ">=12.0.0", + "@types/node": ">=18.0.0", "chai": "^4.2.0", - "ethers": "^5.4.7", + "ethers": "^6.4.0", "hardhat": "^2.11.0", "hardhat-gas-reporter": "^1.0.8", "solidity-coverage": "^0.8.1", "ts-node": ">=8.0.0", - "typechain": "^8.1.0", + "typechain": "^8.3.0", "typescript": ">=4.5.0" } }, + "node_modules/@nomicfoundation/hardhat-verify": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-verify/-/hardhat-verify-2.0.9.tgz", + "integrity": "sha512-7kD8hu1+zlnX87gC+UN4S0HTKBnIsDfXZ/pproq1gYsK94hgCk+exvzXbwR0X2giiY/RZPkqY9oKRi0Uev91hQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/abi": "^5.1.2", + "@ethersproject/address": "^5.0.2", + "cbor": "^8.1.0", + "chalk": "^2.4.2", + "debug": "^4.1.1", + "lodash.clonedeep": "^4.5.0", + "semver": "^6.3.0", + "table": "^6.8.0", + "undici": "^5.14.0" + }, + "peerDependencies": { + "hardhat": "^2.22.72.0.4" + } + }, + "node_modules/@nomicfoundation/ignition-core": { + "version": "0.15.5", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ignition-core/-/ignition-core-0.15.5.tgz", + "integrity": "sha512-FgvuoIXhakRSP524JzNQ4BviyzBBKpsFaOWubPZ4XACLT4/7vGqlJ/7DIn0D2NL2anQ2qs98/BNBY9WccXUX1Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/address": "5.6.1", + "@nomicfoundation/solidity-analyzer": "^0.1.1", + "cbor": "^9.0.0", + "debug": "^4.3.2", + "ethers": "^6.7.0", + "fs-extra": "^10.0.0", + "immer": "10.0.2", + "lodash": "4.17.21", + "ndjson": "2.0.0" + } + }, + "node_modules/@nomicfoundation/ignition-core/node_modules/@ethersproject/address": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.6.1.tgz", + "integrity": "sha512-uOgF0kS5MJv9ZvCz7x6T2EXJSzotiybApn4XlOgoTX0xdtyVIJ7pF+6cGPxiEq/dpBiTfMiw7Yc81JcwhSYA0Q==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/bignumber": "^5.6.2", + "@ethersproject/bytes": "^5.6.1", + "@ethersproject/keccak256": "^5.6.1", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/rlp": "^5.6.1" + } + }, + "node_modules/@nomicfoundation/ignition-core/node_modules/cbor": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-9.0.2.tgz", + "integrity": "sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "nofilter": "^3.1.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@nomicfoundation/ignition-core/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@nomicfoundation/ignition-core/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@nomicfoundation/ignition-core/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@nomicfoundation/ignition-ui": { + "version": "0.15.5", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ignition-ui/-/ignition-ui-0.15.5.tgz", + "integrity": "sha512-ZcE4rIn10qKahR4OqS8rl8NM2Fbg2QYiBXgMgj74ZI0++LlCcZgB5HyaBbX+lsnKHjTXtjYD3b+2mtg7jFbAMQ==", + "dev": true, + "peer": true + }, "node_modules/@nomicfoundation/solidity-analyzer": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.1.tgz", @@ -1740,39 +1492,6 @@ "node": ">= 10" } }, - "node_modules/@nomiclabs/hardhat-ethers": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.2.3.tgz", - "integrity": "sha512-YhzPdzb612X591FOe68q+qXVXGG2ANZRvDo0RRUtimev85rCrAlv/TLMEZw5c+kq9AbzocLTVX/h2jVIFPL9Xg==", - "dev": true, - "peer": true, - "peerDependencies": { - "ethers": "^5.0.0", - "hardhat": "^2.0.0" - } - }, - "node_modules/@nomiclabs/hardhat-etherscan": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.1.7.tgz", - "integrity": "sha512-tZ3TvSgpvsQ6B6OGmo1/Au6u8BrAkvs1mIC/eURA3xgIfznUZBhmpne8hv7BXUzw9xNL3fXdpOYgOQlVMTcoHQ==", - "dev": true, - "peer": true, - "dependencies": { - "@ethersproject/abi": "^5.1.2", - "@ethersproject/address": "^5.0.2", - "cbor": "^8.1.0", - "chalk": "^2.4.2", - "debug": "^4.1.1", - "fs-extra": "^7.0.1", - "lodash": "^4.17.11", - "semver": "^6.3.0", - "table": "^6.8.0", - "undici": "^5.14.0" - }, - "peerDependencies": { - "hardhat": "^2.0.4" - } - }, "node_modules/@openzeppelin/contracts": { "version": "4.8.3", "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.8.3.tgz", @@ -1964,40 +1683,38 @@ "dev": true, "peer": true }, - "node_modules/@typechain/ethers-v5": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/@typechain/ethers-v5/-/ethers-v5-10.2.1.tgz", - "integrity": "sha512-n3tQmCZjRE6IU4h6lqUGiQ1j866n5MTCBJreNEHHVWXa2u9GJTaeYyU1/k+1qLutkyw+sS6VAN+AbeiTqsxd/A==", + "node_modules/@typechain/ethers-v6": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@typechain/ethers-v6/-/ethers-v6-0.5.1.tgz", + "integrity": "sha512-F+GklO8jBWlsaVV+9oHaPh5NJdd6rAKN4tklGfInX1Q7h0xPgVLP39Jl3eCulPB5qexI71ZFHwbljx4ZXNfouA==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "lodash": "^4.17.15", "ts-essentials": "^7.0.1" }, "peerDependencies": { - "@ethersproject/abi": "^5.0.0", - "@ethersproject/providers": "^5.0.0", - "ethers": "^5.1.3", - "typechain": "^8.1.1", - "typescript": ">=4.3.0" + "ethers": "6.x", + "typechain": "^8.3.2", + "typescript": ">=4.7.0" } }, "node_modules/@typechain/hardhat": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/@typechain/hardhat/-/hardhat-6.1.6.tgz", - "integrity": "sha512-BiVnegSs+ZHVymyidtK472syodx1sXYlYJJixZfRstHVGYTi8V1O7QG4nsjyb0PC/LORcq7sfBUcHto1y6UgJA==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@typechain/hardhat/-/hardhat-9.1.0.tgz", + "integrity": "sha512-mtaUlzLlkqTlfPwB3FORdejqBskSnh+Jl8AIJGjXNAQfRQ4ofHADPl1+oU7Z3pAJzmZbUXII8MhOLQltcHgKnA==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "fs-extra": "^9.1.0" }, "peerDependencies": { - "@ethersproject/abi": "^5.4.7", - "@ethersproject/providers": "^5.4.7", - "@typechain/ethers-v5": "^10.2.1", - "ethers": "^5.4.7", + "@typechain/ethers-v6": "^0.5.1", + "ethers": "^6.1.0", "hardhat": "^2.9.9", - "typechain": "^8.1.1" + "typechain": "^8.3.2" } }, "node_modules/@typechain/hardhat/node_modules/fs-extra": { @@ -2005,6 +1722,7 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "at-least-node": "^1.0.0", @@ -2021,6 +1739,7 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "universalify": "^2.0.0" @@ -2030,10 +1749,11 @@ } }, "node_modules/@typechain/hardhat/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">= 10.0.0" @@ -2049,17 +1769,19 @@ } }, "node_modules/@types/chai": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.5.tgz", - "integrity": "sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==", + "version": "4.3.17", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.17.tgz", + "integrity": "sha512-zmZ21EWzR71B4Sscphjief5djsLre50M6lI622OSySTmn9DB3j+C3kWroHfBQWXbOBwbgg/M8CG/hUxDLIloow==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/@types/chai-as-promised": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.5.tgz", - "integrity": "sha512-jStwss93SITGBwt/niYrkf2C+/1KTeZCZl1LaeezTlqppAKeoQC7jxyqYuP72sxBGKCIbw7oHgbYssIRzT5FCQ==", + "version": "7.1.8", + "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.8.tgz", + "integrity": "sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "@types/chai": "*" @@ -2138,10 +1860,11 @@ } }, "node_modules/@types/prettier": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz", - "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==", + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", + "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/@types/qs": { @@ -2151,16 +1874,6 @@ "dev": true, "peer": true }, - "node_modules/@types/readable-stream": { - "version": "2.3.15", - "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-2.3.15.tgz", - "integrity": "sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ==", - "dev": true, - "dependencies": { - "@types/node": "*", - "safe-buffer": "~5.1.1" - } - }, "node_modules/@types/secp256k1": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.3.tgz", @@ -2490,36 +2203,6 @@ "dev": true, "peer": true }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dev": true, - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, - "node_modules/abstract-level": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/abstract-level/-/abstract-level-1.0.3.tgz", - "integrity": "sha512-t6jv+xHy+VYwc4xqZMn2Pa9DjcdzvzZmQGRjTFc8spIbRGHgBrEKbPq+rYXc7CCo0lxgYvSgKVg9qZAhpVQSjA==", - "dev": true, - "dependencies": { - "buffer": "^6.0.3", - "catering": "^2.1.0", - "is-buffer": "^2.0.5", - "level-supports": "^4.0.0", - "level-transcoder": "^1.0.1", - "module-error": "^1.0.1", - "queue-microtask": "^1.2.3" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/acorn": { "version": "8.8.2", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", @@ -2574,7 +2257,8 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==", - "dev": true + "dev": true, + "peer": true }, "node_modules/agent-base": { "version": "6.0.2", @@ -2628,6 +2312,16 @@ "node": ">=0.4.2" } }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.1.0" + } + }, "node_modules/ansi-colors": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", @@ -2719,6 +2413,7 @@ "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=6" @@ -2809,6 +2504,7 @@ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": "*" @@ -2848,6 +2544,7 @@ "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", "dev": true, + "license": "ISC", "peer": true, "engines": { "node": ">= 4.0.0" @@ -2898,26 +2595,6 @@ "safe-buffer": "^5.0.1" } }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", @@ -2935,21 +2612,6 @@ "dev": true, "peer": true }, - "node_modules/bech32": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", - "dev": true - }, - "node_modules/bigint-crypto-utils": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/bigint-crypto-utils/-/bigint-crypto-utils-3.2.2.tgz", - "integrity": "sha512-U1RbE3aX9ayCUVcIPHuPDPKcK3SFOXf93J1UK/iHlJuQB7bhagPIX06/CLpLEsDThJ7KA4Dhrnzynl+d2weTiw==", - "dev": true, - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -2971,6 +2633,118 @@ "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", "dev": true }, + "node_modules/boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/boxen/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/boxen/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/boxen/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/boxen/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/boxen/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/boxen/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -2982,12 +2756,12 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -2999,18 +2773,6 @@ "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", "dev": true }, - "node_modules/browser-level": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browser-level/-/browser-level-1.0.1.tgz", - "integrity": "sha512-XECYKJ+Dbzw0lbydyQuJzwNXtOpbMSq737qxJN11sIRTErOMShvDpbzTlgju7orJKvx4epULolZAuJGLzCmWRQ==", - "dev": true, - "dependencies": { - "abstract-level": "^1.0.2", - "catering": "^2.1.1", - "module-error": "^1.0.2", - "run-parallel-limit": "^1.1.0" - } - }, "node_modules/browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", @@ -3051,30 +2813,6 @@ "safe-buffer": "^5.1.2" } }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -3087,18 +2825,6 @@ "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", "dev": true }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "dev": true, - "dependencies": { - "streamsearch": "^1.1.0" - }, - "engines": { - "node": ">=10.16.0" - } - }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -3113,6 +2839,7 @@ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", "dev": true, + "peer": true, "dependencies": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" @@ -3142,15 +2869,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/case": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/case/-/case-1.6.3.tgz", - "integrity": "sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -3158,20 +2876,12 @@ "dev": true, "peer": true }, - "node_modules/catering": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/catering/-/catering-2.1.1.tgz", - "integrity": "sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/cbor": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/cbor/-/cbor-8.1.0.tgz", "integrity": "sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "nofilter": "^3.1.0" @@ -3181,35 +2891,37 @@ } }, "node_modules/chai": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", - "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", + "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^4.1.2", - "get-func-name": "^2.0.0", - "loupe": "^2.3.1", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", "pathval": "^1.1.1", - "type-detect": "^4.0.5" + "type-detect": "^4.1.0" }, "engines": { "node": ">=4" } }, "node_modules/chai-as-promised": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", - "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.2.tgz", + "integrity": "sha512-aBDHZxRzYnUYuIAIPBH2s511DjlKPzXNlXSGFC8CwmroWQLfrW0LtE1nK3MAwwNhJPa9raEjNCmRoFpG0Hurdw==", "dev": true, + "license": "WTFPL", "peer": true, "dependencies": { "check-error": "^1.0.2" }, "peerDependencies": { - "chai": ">= 2.1.2 < 5" + "chai": ">= 2.1.2 < 6" } }, "node_modules/chalk": { @@ -3237,11 +2949,15 @@ } }, "node_modules/check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", "dev": true, + "license": "MIT", "peer": true, + "dependencies": { + "get-func-name": "^2.0.2" + }, "engines": { "node": "*" } @@ -3289,23 +3005,6 @@ "safe-buffer": "^5.0.1" } }, - "node_modules/classic-level": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/classic-level/-/classic-level-1.3.0.tgz", - "integrity": "sha512-iwFAJQYtqRTRM0F6L8h4JCt00ZSGdOyqh7yVrhhjrOpFhmBjNlRUey64MCiyo6UmQHMJ+No3c81nujPv+n9yrg==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "abstract-level": "^1.0.2", - "catering": "^2.1.0", - "module-error": "^1.0.1", - "napi-macros": "^2.2.2", - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", @@ -3315,6 +3014,19 @@ "node": ">=6" } }, + "node_modules/cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/cli-table3": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.5.1.tgz", @@ -3432,13 +3144,15 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/command-line-args": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "array-back": "^3.1.0", @@ -3455,6 +3169,7 @@ "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.3.tgz", "integrity": "sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "array-back": "^4.0.2", @@ -3471,6 +3186,7 @@ "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -3481,16 +3197,21 @@ "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=8" } }, "node_modules/commander": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", - "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==", - "dev": true + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } }, "node_modules/concat-map": { "version": "0.0.1", @@ -3574,18 +3295,6 @@ "url": "https://github.com/sponsors/d-fischer" } }, - "node_modules/crc-32": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", - "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", - "dev": true, - "bin": { - "crc32": "bin/crc32.njs" - }, - "engines": { - "node": ">=0.8" - } - }, "node_modules/create-hash": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", @@ -3709,10 +3418,11 @@ } }, "node_modules/deep-eql": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", - "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", + "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "type-detect": "^4.0.0" @@ -3726,6 +3436,7 @@ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=4.0.0" @@ -5194,51 +4905,94 @@ } }, "node_modules/ethers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", - "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.2.tgz", + "integrity": "sha512-9VkriTTed+/27BGuY1s0hf441kqwHJ1wtN2edksEtiRvXx+soxRX3iSXTfFqq2+YwrOqbDoTHjIhQnjJRlzKmg==", "dev": true, "funding": [ { "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + "url": "https://github.com/sponsors/ethers-io/" }, { "type": "individual", "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", + "peer": true, "dependencies": { - "@ethersproject/abi": "5.7.0", - "@ethersproject/abstract-provider": "5.7.0", - "@ethersproject/abstract-signer": "5.7.0", - "@ethersproject/address": "5.7.0", - "@ethersproject/base64": "5.7.0", - "@ethersproject/basex": "5.7.0", - "@ethersproject/bignumber": "5.7.0", - "@ethersproject/bytes": "5.7.0", - "@ethersproject/constants": "5.7.0", - "@ethersproject/contracts": "5.7.0", - "@ethersproject/hash": "5.7.0", - "@ethersproject/hdnode": "5.7.0", - "@ethersproject/json-wallets": "5.7.0", - "@ethersproject/keccak256": "5.7.0", - "@ethersproject/logger": "5.7.0", - "@ethersproject/networks": "5.7.1", - "@ethersproject/pbkdf2": "5.7.0", - "@ethersproject/properties": "5.7.0", - "@ethersproject/providers": "5.7.2", - "@ethersproject/random": "5.7.0", - "@ethersproject/rlp": "5.7.0", - "@ethersproject/sha2": "5.7.0", - "@ethersproject/signing-key": "5.7.0", - "@ethersproject/solidity": "5.7.0", - "@ethersproject/strings": "5.7.0", - "@ethersproject/transactions": "5.7.0", - "@ethersproject/units": "5.7.0", - "@ethersproject/wallet": "5.7.0", - "@ethersproject/web": "5.7.1", - "@ethersproject/wordlists": "5.7.0" + "@adraffy/ens-normalize": "1.10.1", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", + "@types/node": "18.15.13", + "aes-js": "4.0.0-beta.5", + "tslib": "2.4.0", + "ws": "8.17.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/ethers/node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ethers/node_modules/@types/node": { + "version": "18.15.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", + "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/ethers/node_modules/aes-js": { + "version": "4.0.0-beta.5", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", + "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/ethers/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "dev": true, + "license": "0BSD", + "peer": true + }, + "node_modules/ethers/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, "node_modules/ethjs-unit": { @@ -5277,15 +5031,6 @@ "npm": ">=3" } }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/evp_bytestokey": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", @@ -5375,9 +5120,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" @@ -5391,6 +5136,7 @@ "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "array-back": "^3.0.1" @@ -5455,9 +5201,9 @@ "dev": true }, "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "dev": true, "funding": [ { @@ -5465,6 +5211,7 @@ "url": "https://github.com/sponsors/RubenVerborgh" } ], + "license": "MIT", "engines": { "node": ">=4.0" }, @@ -5560,7 +5307,8 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "dev": true, + "peer": true }, "node_modules/function.prototype.name": { "version": "1.1.5", @@ -5581,12 +5329,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", - "dev": true - }, "node_modules/functions-have-names": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", @@ -5607,10 +5349,11 @@ } }, "node_modules/get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": "*" @@ -5621,6 +5364,7 @@ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", "dev": true, + "peer": true, "dependencies": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -5888,31 +5632,26 @@ } }, "node_modules/hardhat": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.14.0.tgz", - "integrity": "sha512-73jsInY4zZahMSVFurSK+5TNCJTXMv+vemvGia0Ac34Mm19fYp6vEPVGF3sucbumszsYxiTT2TbS8Ii2dsDSoQ==", + "version": "2.22.8", + "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.22.8.tgz", + "integrity": "sha512-hPh2feBGRswkXkoXUFW6NbxgiYtEzp/3uvVFjYROy6fA9LH8BobUyxStlyhSKj4+v1Y23ZoUBOVWL84IcLACrA==", "dev": true, + "license": "MIT", "dependencies": { "@ethersproject/abi": "^5.1.2", "@metamask/eth-sig-util": "^4.0.0", - "@nomicfoundation/ethereumjs-block": "5.0.1", - "@nomicfoundation/ethereumjs-blockchain": "7.0.1", - "@nomicfoundation/ethereumjs-common": "4.0.1", - "@nomicfoundation/ethereumjs-evm": "2.0.1", - "@nomicfoundation/ethereumjs-rlp": "5.0.1", - "@nomicfoundation/ethereumjs-statemanager": "2.0.1", - "@nomicfoundation/ethereumjs-trie": "6.0.1", - "@nomicfoundation/ethereumjs-tx": "5.0.1", - "@nomicfoundation/ethereumjs-util": "9.0.1", - "@nomicfoundation/ethereumjs-vm": "7.0.1", + "@nomicfoundation/edr": "^0.5.2", + "@nomicfoundation/ethereumjs-common": "4.0.4", + "@nomicfoundation/ethereumjs-tx": "5.0.4", + "@nomicfoundation/ethereumjs-util": "9.0.4", "@nomicfoundation/solidity-analyzer": "^0.1.0", "@sentry/node": "^5.18.1", "@types/bn.js": "^5.1.0", "@types/lru-cache": "^5.1.0", - "abort-controller": "^3.0.0", "adm-zip": "^0.4.16", "aggregate-error": "^3.0.0", "ansi-escapes": "^4.3.0", + "boxen": "^5.1.2", "chalk": "^2.4.2", "chokidar": "^3.4.0", "ci-info": "^2.0.0", @@ -5932,11 +5671,10 @@ "mnemonist": "^0.38.0", "mocha": "^10.0.0", "p-map": "^4.0.0", - "qs": "^6.7.0", "raw-body": "^2.4.1", "resolve": "1.17.0", "semver": "^6.3.0", - "solc": "0.7.3", + "solc": "0.8.26", "source-map-support": "^0.5.13", "stacktrace-parser": "^0.1.10", "tsort": "0.0.1", @@ -5947,9 +5685,6 @@ "bin": { "hardhat": "internal/cli/bootstrap.js" }, - "engines": { - "node": ">=14.0.0" - }, "peerDependencies": { "ts-node": "*", "typescript": "*" @@ -5983,6 +5718,7 @@ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, + "peer": true, "dependencies": { "function-bind": "^1.1.1" }, @@ -6027,6 +5763,7 @@ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", "dev": true, + "peer": true, "engines": { "node": ">= 0.4" }, @@ -6039,6 +5776,7 @@ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "dev": true, + "peer": true, "engines": { "node": ">= 0.4" }, @@ -6223,26 +5961,6 @@ "node": ">=0.10.0" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/ignore": { "version": "5.2.4", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", @@ -6252,6 +5970,18 @@ "node": ">= 4" } }, + "node_modules/immer": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.0.2.tgz", + "integrity": "sha512-Rx3CqeqQ19sxUtYV9CU911Vhy8/721wRFnJv3REVGWUmoAcIwzifTsdmJte/MV+0/XpM35LZdQMBGkRIoLPwQA==", + "dev": true, + "license": "MIT", + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, "node_modules/immutable": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz", @@ -6440,6 +6170,7 @@ "url": "https://feross.org/support" } ], + "peer": true, "engines": { "node": ">=4" } @@ -6836,52 +6567,15 @@ "node": ">=0.10.0" } }, - "node_modules/klaw": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", - "integrity": "sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==", + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.9" - } - }, - "node_modules/level": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/level/-/level-8.0.0.tgz", - "integrity": "sha512-ypf0jjAk2BWI33yzEaaotpq7fkOPALKAgDBxggO6Q9HGX2MRXn0wbP1Jn/tJv1gtL867+YOjOB49WaUF3UoJNQ==", - "dev": true, - "dependencies": { - "browser-level": "^1.0.1", - "classic-level": "^1.2.0" - }, + "license": "MIT", + "peer": true, "engines": { - "node": ">=12" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/level" - } - }, - "node_modules/level-supports": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-4.0.1.tgz", - "integrity": "sha512-PbXpve8rKeNcZ9C1mUicC9auIYFyGpkV9/i6g76tLgANwWhtG2v7I4xNBUlkn3lE2/dZF3Pi0ygYGtLc4RXXdA==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/level-transcoder": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/level-transcoder/-/level-transcoder-1.0.1.tgz", - "integrity": "sha512-t7bFwFtsQeD8cl8NIoQ2iwxA0CL/9IFw7/9gAjOonH0PWTTiRfY7Hq+Ejbsxh86tXobDQ6IOiddjNYIfOBs06w==", - "dev": true, - "dependencies": { - "buffer": "^6.0.3", - "module-error": "^1.0.1" - }, - "engines": { - "node": ">=12" + "node": ">=6" } }, "node_modules/levn": { @@ -6928,6 +6622,23 @@ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "dev": true, + "license": "MIT", "peer": true }, "node_modules/lodash.merge": { @@ -7029,13 +6740,14 @@ } }, "node_modules/loupe": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", - "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { - "get-func-name": "^2.0.0" + "get-func-name": "^2.0.1" } }, "node_modules/lru_map": { @@ -7044,15 +6756,6 @@ "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==", "dev": true }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -7067,15 +6770,6 @@ "dev": true, "peer": true }, - "node_modules/mcl-wasm": { - "version": "0.7.9", - "resolved": "https://registry.npmjs.org/mcl-wasm/-/mcl-wasm-0.7.9.tgz", - "integrity": "sha512-iJIUcQWA88IJB/5L15GnJVnSQJmf/YaxxV6zRavv83HILHaJQb6y0iFyDMdDO0gN8X37tdxmAOrH/P8B6RB8sQ==", - "dev": true, - "engines": { - "node": ">=8.9.0" - } - }, "node_modules/md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -7087,20 +6781,6 @@ "safe-buffer": "^5.1.2" } }, - "node_modules/memory-level": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/memory-level/-/memory-level-1.0.0.tgz", - "integrity": "sha512-UXzwewuWeHBz5krr7EvehKcmLFNoXxGcvuYhC41tRnkrTbJohtS7kVn9akmgirtRygg+f7Yjsfi8Uu5SGSQ4Og==", - "dev": true, - "dependencies": { - "abstract-level": "^1.0.0", - "functional-red-black-tree": "^1.0.1", - "module-error": "^1.0.1" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/memorystream": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", @@ -7393,15 +7073,6 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/module-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/module-error/-/module-error-1.0.2.tgz", - "integrity": "sha512-0yuvsqSCv8LbaOKhnsQ/T5JhyFlCYLPXK3U2sgV10zoKQwzs/MyfuQUOZQ1V/6OCOJsK/TRgNVrPuPDqtdMFtA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -7420,12 +7091,6 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/napi-macros": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/napi-macros/-/napi-macros-2.2.2.tgz", - "integrity": "sha512-hmEVtAGYzVQpCKdbQea4skABsdXW4RUh5t5mJ2zzqowJS2OyXZTU1KhDVFhx+NlWZ4ap9mqR9TcDO3LTTttd+g==", - "dev": true - }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -7438,6 +7103,27 @@ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", "dev": true }, + "node_modules/ndjson": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ndjson/-/ndjson-2.0.0.tgz", + "integrity": "sha512-nGl7LRGrzugTtaFcJMhLbpzJM6XdivmbkdlaGcrk/LXg2KL/YBC6z1g70xh0/al+oFuVFP8N8kiWRucmeEH/qQ==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "json-stringify-safe": "^5.0.1", + "minimist": "^1.2.5", + "readable-stream": "^3.6.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + }, + "bin": { + "ndjson": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -7498,6 +7184,7 @@ "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz", "integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=12.19" @@ -7572,6 +7259,7 @@ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", "dev": true, + "peer": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -7660,6 +7348,7 @@ "resolved": "https://registry.npmjs.org/ordinal/-/ordinal-1.0.3.tgz", "integrity": "sha512-cMddMgb2QElm8G7vdaa02jhUNbTSrhsgAGUz1OokD83uJTwSUn+nKoNoKVVaRa08yF6sgfO7Maou1+bgLd9rdQ==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/os-tmpdir": { @@ -7667,6 +7356,7 @@ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -7803,6 +7493,7 @@ "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": "*" @@ -7975,6 +7666,21 @@ "asap": "~2.0.6" } }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", @@ -7996,6 +7702,7 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", "dev": true, + "peer": true, "dependencies": { "side-channel": "^1.0.4" }, @@ -8107,6 +7814,7 @@ "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz", "integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=6" @@ -8302,18 +8010,6 @@ "node": ">=0.10.0" } }, - "node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, "node_modules/ripemd160": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", @@ -8359,35 +8055,6 @@ "queue-microtask": "^1.2.2" } }, - "node_modules/run-parallel-limit": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/run-parallel-limit/-/run-parallel-limit-1.1.0.tgz", - "integrity": "sha512-jJA7irRNM91jaKc3Hcl1npHsFLOXOoTkPCUL1JEa1R82O2miplXXRaGdjW/KM/98YQWDhJLiSs793CnXfblJUw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/rustbn.js": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.2.0.tgz", - "integrity": "sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA==", - "dev": true - }, "node_modules/safe-array-concat": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz", @@ -8681,6 +8348,7 @@ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", "dev": true, + "peer": true, "dependencies": { "call-bind": "^1.0.0", "get-intrinsic": "^1.0.2", @@ -8690,6 +8358,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -8750,55 +8426,33 @@ "dev": true }, "node_modules/solc": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/solc/-/solc-0.7.3.tgz", - "integrity": "sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA==", + "version": "0.8.26", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.8.26.tgz", + "integrity": "sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g==", "dev": true, + "license": "MIT", "dependencies": { "command-exists": "^1.2.8", - "commander": "3.0.2", + "commander": "^8.1.0", "follow-redirects": "^1.12.1", - "fs-extra": "^0.30.0", "js-sha3": "0.8.0", "memorystream": "^0.3.1", - "require-from-string": "^2.0.0", "semver": "^5.5.0", "tmp": "0.0.33" }, "bin": { - "solcjs": "solcjs" + "solcjs": "solc.js" }, "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/solc/node_modules/fs-extra": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", - "integrity": "sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0", - "path-is-absolute": "^1.0.0", - "rimraf": "^2.2.8" - } - }, - "node_modules/solc/node_modules/jsonfile": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "node": ">=10.0.0" } }, "node_modules/solc/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver" } @@ -9557,6 +9211,17 @@ "source-map": "^0.6.0" } }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "readable-stream": "^3.0.0" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -9637,15 +9302,6 @@ "node": ">=0.10.0" } }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -9680,6 +9336,7 @@ "resolved": "https://registry.npmjs.org/string-format/-/string-format-2.0.0.tgz", "integrity": "sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==", "dev": true, + "license": "WTFPL OR MIT", "peer": true }, "node_modules/string-width": { @@ -9839,6 +9496,7 @@ "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-1.0.2.tgz", "integrity": "sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "array-back": "^4.0.1", @@ -9855,6 +9513,7 @@ "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -9865,6 +9524,7 @@ "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -9928,11 +9588,23 @@ "dev": true, "peer": true }, + "node_modules/through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "readable-stream": "3" + } + }, "node_modules/tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, + "license": "MIT", "dependencies": { "os-tmpdir": "~1.0.2" }, @@ -9976,13 +9648,13 @@ } }, "node_modules/ts-command-line-args": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/ts-command-line-args/-/ts-command-line-args-2.5.0.tgz", - "integrity": "sha512-Ff7Xt04WWCjj/cmPO9eWTJX3qpBZWuPWyQYG1vnxJao+alWWYjwJBc5aYz3h5p5dE08A6AnpkgiCtP/0KXXBYw==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/ts-command-line-args/-/ts-command-line-args-2.5.1.tgz", + "integrity": "sha512-H69ZwTw3rFHb5WYpQya40YAX2/w7Ut75uUECbgBIsLmM+BNuYnxsltfyyLMxy6sEeKxgijLTnQtLd0nKd6+IYw==", "dev": true, + "license": "ISC", "peer": true, "dependencies": { - "@morgan-stanley/ts-mocking-bird": "^0.6.2", "chalk": "^4.1.0", "command-line-args": "^5.1.1", "command-line-usage": "^6.1.0", @@ -9997,6 +9669,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "color-convert": "^2.0.1" @@ -10013,6 +9686,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "ansi-styles": "^4.1.0", @@ -10030,6 +9704,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "color-name": "~1.1.4" @@ -10043,6 +9718,7 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/ts-command-line-args/node_modules/has-flag": { @@ -10050,6 +9726,7 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -10060,6 +9737,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "has-flag": "^4.0.0" @@ -10073,6 +9751,7 @@ "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-7.0.3.tgz", "integrity": "sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==", "dev": true, + "license": "MIT", "peer": true, "peerDependencies": { "typescript": ">=3.7.0" @@ -10198,10 +9877,11 @@ } }, "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=4" @@ -10220,10 +9900,11 @@ } }, "node_modules/typechain": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/typechain/-/typechain-8.1.1.tgz", - "integrity": "sha512-uF/sUvnXTOVF2FHKhQYnxHk4su4JjZR8vr4mA2mBaRwHTbwh0jIlqARz9XJr1tA0l7afJGvEa1dTSi4zt039LQ==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/typechain/-/typechain-8.3.2.tgz", + "integrity": "sha512-x/sQYr5w9K7yv3es7jo4KTX05CLxOf7TRWwoHlrjRh8H82G64g+k7VuWPJlgMo6qrjfCulOdfBjiaDtmhFYD/Q==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "@types/prettier": "^2.1.1", @@ -10248,7 +9929,9 @@ "version": "7.1.7", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, + "license": "ISC", "peer": true, "dependencies": { "fs.realpath": "^1.0.0", @@ -10270,6 +9953,7 @@ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, + "license": "MIT", "peer": true, "bin": { "mkdirp": "bin/cmd.js" @@ -10318,6 +10002,7 @@ "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -10354,12 +10039,12 @@ } }, "node_modules/undici": { - "version": "5.22.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.22.1.tgz", - "integrity": "sha512-Ji2IJhFXZY0x/0tVBXeQwgPlLWw13GVzpsWPQ3rV50IFMMof2I55PZZxtm4P6iNq+L5znYN9nSTAq0ZyE6lSJw==", + "version": "5.28.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", + "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", "dev": true, "dependencies": { - "busboy": "^1.6.0" + "@fastify/busboy": "^2.0.0" }, "engines": { "node": ">=14.0" @@ -10611,6 +10296,19 @@ "node": ">=4" } }, + "node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", @@ -10632,6 +10330,7 @@ "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.1.tgz", "integrity": "sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "reduce-flatten": "^2.0.0", @@ -10646,6 +10345,7 @@ "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -10753,12 +10453,6 @@ "node": ">=10" } }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, "node_modules/yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", diff --git a/contracts/package.json b/contracts/package.json index 0eea2694..1c59e3ec 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -5,7 +5,7 @@ "private": true, "description": "Solidity contracts for 0g Blockchain", "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" }, "scripts": { "build": "npm run clean && npm run compile && npm run ethermint-json", @@ -23,14 +23,14 @@ "test": "hardhat test" }, "devDependencies": { - "@nomicfoundation/hardhat-toolbox": "^2.0.2", + "@nomicfoundation/hardhat-toolbox": "^5.0.0", "@openzeppelin/contracts": "4.8.3", "@typescript-eslint/eslint-plugin": "^5.59.6", "@typescript-eslint/parser": "^5.59.6", "eslint": "^8.40.0", "eslint-config-prettier": "8.8.0", "eslint-plugin-prettier": "^4.2.1", - "hardhat": "^2.14.0", + "hardhat": "^2.22.8", "prettier": "2.8.8", "prettier-plugin-solidity": "^1.1.3", "solhint": "^3.4.1", diff --git a/contrib/devnet/init-new-chain.sh b/contrib/devnet/init-new-chain.sh index 9666a1aa..d35ffe14 100755 --- a/contrib/devnet/init-new-chain.sh +++ b/contrib/devnet/init-new-chain.sh @@ -26,7 +26,7 @@ rm -rf $DATA BINARY=kava -# Create new data directory, overwriting any that alread existed +# Create new data directory, overwriting any that already existed chainID="kavalocalnet_8888-1" $BINARY init validator --chain-id $chainID diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md index 0fecc502..018dd494 100644 --- a/docs/core/proto-docs.md +++ b/docs/core/proto-docs.md @@ -4,256 +4,595 @@ ## Table of Contents -- [crypto/vrf/keys.proto](#crypto/vrf/keys.proto) - - [PrivKey](#crypto.vrf.PrivKey) - - [PubKey](#crypto.vrf.PubKey) +- [kava/auction/v1beta1/auction.proto](#kava/auction/v1beta1/auction.proto) + - [BaseAuction](#kava.auction.v1beta1.BaseAuction) + - [CollateralAuction](#kava.auction.v1beta1.CollateralAuction) + - [DebtAuction](#kava.auction.v1beta1.DebtAuction) + - [SurplusAuction](#kava.auction.v1beta1.SurplusAuction) + - [WeightedAddresses](#kava.auction.v1beta1.WeightedAddresses) -- [zgc/bep3/v1beta1/bep3.proto](#zgc/bep3/v1beta1/bep3.proto) - - [AssetParam](#zgc.bep3.v1beta1.AssetParam) - - [AssetSupply](#zgc.bep3.v1beta1.AssetSupply) - - [AtomicSwap](#zgc.bep3.v1beta1.AtomicSwap) - - [Params](#zgc.bep3.v1beta1.Params) - - [SupplyLimit](#zgc.bep3.v1beta1.SupplyLimit) +- [kava/auction/v1beta1/genesis.proto](#kava/auction/v1beta1/genesis.proto) + - [GenesisState](#kava.auction.v1beta1.GenesisState) + - [Params](#kava.auction.v1beta1.Params) - - [SwapDirection](#zgc.bep3.v1beta1.SwapDirection) - - [SwapStatus](#zgc.bep3.v1beta1.SwapStatus) +- [kava/auction/v1beta1/query.proto](#kava/auction/v1beta1/query.proto) + - [QueryAuctionRequest](#kava.auction.v1beta1.QueryAuctionRequest) + - [QueryAuctionResponse](#kava.auction.v1beta1.QueryAuctionResponse) + - [QueryAuctionsRequest](#kava.auction.v1beta1.QueryAuctionsRequest) + - [QueryAuctionsResponse](#kava.auction.v1beta1.QueryAuctionsResponse) + - [QueryNextAuctionIDRequest](#kava.auction.v1beta1.QueryNextAuctionIDRequest) + - [QueryNextAuctionIDResponse](#kava.auction.v1beta1.QueryNextAuctionIDResponse) + - [QueryParamsRequest](#kava.auction.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#kava.auction.v1beta1.QueryParamsResponse) -- [zgc/bep3/v1beta1/genesis.proto](#zgc/bep3/v1beta1/genesis.proto) - - [GenesisState](#zgc.bep3.v1beta1.GenesisState) + - [Query](#kava.auction.v1beta1.Query) -- [zgc/bep3/v1beta1/query.proto](#zgc/bep3/v1beta1/query.proto) - - [AssetSupplyResponse](#zgc.bep3.v1beta1.AssetSupplyResponse) - - [AtomicSwapResponse](#zgc.bep3.v1beta1.AtomicSwapResponse) - - [QueryAssetSuppliesRequest](#zgc.bep3.v1beta1.QueryAssetSuppliesRequest) - - [QueryAssetSuppliesResponse](#zgc.bep3.v1beta1.QueryAssetSuppliesResponse) - - [QueryAssetSupplyRequest](#zgc.bep3.v1beta1.QueryAssetSupplyRequest) - - [QueryAssetSupplyResponse](#zgc.bep3.v1beta1.QueryAssetSupplyResponse) - - [QueryAtomicSwapRequest](#zgc.bep3.v1beta1.QueryAtomicSwapRequest) - - [QueryAtomicSwapResponse](#zgc.bep3.v1beta1.QueryAtomicSwapResponse) - - [QueryAtomicSwapsRequest](#zgc.bep3.v1beta1.QueryAtomicSwapsRequest) - - [QueryAtomicSwapsResponse](#zgc.bep3.v1beta1.QueryAtomicSwapsResponse) - - [QueryParamsRequest](#zgc.bep3.v1beta1.QueryParamsRequest) - - [QueryParamsResponse](#zgc.bep3.v1beta1.QueryParamsResponse) +- [kava/auction/v1beta1/tx.proto](#kava/auction/v1beta1/tx.proto) + - [MsgPlaceBid](#kava.auction.v1beta1.MsgPlaceBid) + - [MsgPlaceBidResponse](#kava.auction.v1beta1.MsgPlaceBidResponse) - - [Query](#zgc.bep3.v1beta1.Query) + - [Msg](#kava.auction.v1beta1.Msg) -- [zgc/bep3/v1beta1/tx.proto](#zgc/bep3/v1beta1/tx.proto) - - [MsgClaimAtomicSwap](#zgc.bep3.v1beta1.MsgClaimAtomicSwap) - - [MsgClaimAtomicSwapResponse](#zgc.bep3.v1beta1.MsgClaimAtomicSwapResponse) - - [MsgCreateAtomicSwap](#zgc.bep3.v1beta1.MsgCreateAtomicSwap) - - [MsgCreateAtomicSwapResponse](#zgc.bep3.v1beta1.MsgCreateAtomicSwapResponse) - - [MsgRefundAtomicSwap](#zgc.bep3.v1beta1.MsgRefundAtomicSwap) - - [MsgRefundAtomicSwapResponse](#zgc.bep3.v1beta1.MsgRefundAtomicSwapResponse) +- [kava/bep3/v1beta1/bep3.proto](#kava/bep3/v1beta1/bep3.proto) + - [AssetParam](#kava.bep3.v1beta1.AssetParam) + - [AssetSupply](#kava.bep3.v1beta1.AssetSupply) + - [AtomicSwap](#kava.bep3.v1beta1.AtomicSwap) + - [Params](#kava.bep3.v1beta1.Params) + - [SupplyLimit](#kava.bep3.v1beta1.SupplyLimit) - - [Msg](#zgc.bep3.v1beta1.Msg) + - [SwapDirection](#kava.bep3.v1beta1.SwapDirection) + - [SwapStatus](#kava.bep3.v1beta1.SwapStatus) -- [zgc/committee/v1beta1/committee.proto](#zgc/committee/v1beta1/committee.proto) - - [BaseCommittee](#zgc.committee.v1beta1.BaseCommittee) - - [MemberCommittee](#zgc.committee.v1beta1.MemberCommittee) - - [TokenCommittee](#zgc.committee.v1beta1.TokenCommittee) +- [kava/bep3/v1beta1/genesis.proto](#kava/bep3/v1beta1/genesis.proto) + - [GenesisState](#kava.bep3.v1beta1.GenesisState) - - [TallyOption](#zgc.committee.v1beta1.TallyOption) +- [kava/bep3/v1beta1/query.proto](#kava/bep3/v1beta1/query.proto) + - [AssetSupplyResponse](#kava.bep3.v1beta1.AssetSupplyResponse) + - [AtomicSwapResponse](#kava.bep3.v1beta1.AtomicSwapResponse) + - [QueryAssetSuppliesRequest](#kava.bep3.v1beta1.QueryAssetSuppliesRequest) + - [QueryAssetSuppliesResponse](#kava.bep3.v1beta1.QueryAssetSuppliesResponse) + - [QueryAssetSupplyRequest](#kava.bep3.v1beta1.QueryAssetSupplyRequest) + - [QueryAssetSupplyResponse](#kava.bep3.v1beta1.QueryAssetSupplyResponse) + - [QueryAtomicSwapRequest](#kava.bep3.v1beta1.QueryAtomicSwapRequest) + - [QueryAtomicSwapResponse](#kava.bep3.v1beta1.QueryAtomicSwapResponse) + - [QueryAtomicSwapsRequest](#kava.bep3.v1beta1.QueryAtomicSwapsRequest) + - [QueryAtomicSwapsResponse](#kava.bep3.v1beta1.QueryAtomicSwapsResponse) + - [QueryParamsRequest](#kava.bep3.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#kava.bep3.v1beta1.QueryParamsResponse) -- [zgc/committee/v1beta1/genesis.proto](#zgc/committee/v1beta1/genesis.proto) - - [GenesisState](#zgc.committee.v1beta1.GenesisState) - - [Proposal](#zgc.committee.v1beta1.Proposal) - - [Vote](#zgc.committee.v1beta1.Vote) + - [Query](#kava.bep3.v1beta1.Query) - - [VoteType](#zgc.committee.v1beta1.VoteType) +- [kava/bep3/v1beta1/tx.proto](#kava/bep3/v1beta1/tx.proto) + - [MsgClaimAtomicSwap](#kava.bep3.v1beta1.MsgClaimAtomicSwap) + - [MsgClaimAtomicSwapResponse](#kava.bep3.v1beta1.MsgClaimAtomicSwapResponse) + - [MsgCreateAtomicSwap](#kava.bep3.v1beta1.MsgCreateAtomicSwap) + - [MsgCreateAtomicSwapResponse](#kava.bep3.v1beta1.MsgCreateAtomicSwapResponse) + - [MsgRefundAtomicSwap](#kava.bep3.v1beta1.MsgRefundAtomicSwap) + - [MsgRefundAtomicSwapResponse](#kava.bep3.v1beta1.MsgRefundAtomicSwapResponse) -- [zgc/committee/v1beta1/permissions.proto](#zgc/committee/v1beta1/permissions.proto) - - [AllowedParamsChange](#zgc.committee.v1beta1.AllowedParamsChange) - - [CommunityCDPRepayDebtPermission](#zgc.committee.v1beta1.CommunityCDPRepayDebtPermission) - - [CommunityCDPWithdrawCollateralPermission](#zgc.committee.v1beta1.CommunityCDPWithdrawCollateralPermission) - - [CommunityPoolLendWithdrawPermission](#zgc.committee.v1beta1.CommunityPoolLendWithdrawPermission) - - [GodPermission](#zgc.committee.v1beta1.GodPermission) - - [ParamsChangePermission](#zgc.committee.v1beta1.ParamsChangePermission) - - [SoftwareUpgradePermission](#zgc.committee.v1beta1.SoftwareUpgradePermission) - - [SubparamRequirement](#zgc.committee.v1beta1.SubparamRequirement) - - [TextPermission](#zgc.committee.v1beta1.TextPermission) + - [Msg](#kava.bep3.v1beta1.Msg) -- [zgc/committee/v1beta1/proposal.proto](#zgc/committee/v1beta1/proposal.proto) - - [CommitteeChangeProposal](#zgc.committee.v1beta1.CommitteeChangeProposal) - - [CommitteeDeleteProposal](#zgc.committee.v1beta1.CommitteeDeleteProposal) +- [kava/cdp/v1beta1/cdp.proto](#kava/cdp/v1beta1/cdp.proto) + - [CDP](#kava.cdp.v1beta1.CDP) + - [Deposit](#kava.cdp.v1beta1.Deposit) + - [OwnerCDPIndex](#kava.cdp.v1beta1.OwnerCDPIndex) + - [TotalCollateral](#kava.cdp.v1beta1.TotalCollateral) + - [TotalPrincipal](#kava.cdp.v1beta1.TotalPrincipal) -- [zgc/committee/v1beta1/query.proto](#zgc/committee/v1beta1/query.proto) - - [QueryCommitteeRequest](#zgc.committee.v1beta1.QueryCommitteeRequest) - - [QueryCommitteeResponse](#zgc.committee.v1beta1.QueryCommitteeResponse) - - [QueryCommitteesRequest](#zgc.committee.v1beta1.QueryCommitteesRequest) - - [QueryCommitteesResponse](#zgc.committee.v1beta1.QueryCommitteesResponse) - - [QueryNextProposalIDRequest](#zgc.committee.v1beta1.QueryNextProposalIDRequest) - - [QueryNextProposalIDResponse](#zgc.committee.v1beta1.QueryNextProposalIDResponse) - - [QueryProposalRequest](#zgc.committee.v1beta1.QueryProposalRequest) - - [QueryProposalResponse](#zgc.committee.v1beta1.QueryProposalResponse) - - [QueryProposalsRequest](#zgc.committee.v1beta1.QueryProposalsRequest) - - [QueryProposalsResponse](#zgc.committee.v1beta1.QueryProposalsResponse) - - [QueryRawParamsRequest](#zgc.committee.v1beta1.QueryRawParamsRequest) - - [QueryRawParamsResponse](#zgc.committee.v1beta1.QueryRawParamsResponse) - - [QueryTallyRequest](#zgc.committee.v1beta1.QueryTallyRequest) - - [QueryTallyResponse](#zgc.committee.v1beta1.QueryTallyResponse) - - [QueryVoteRequest](#zgc.committee.v1beta1.QueryVoteRequest) - - [QueryVoteResponse](#zgc.committee.v1beta1.QueryVoteResponse) - - [QueryVotesRequest](#zgc.committee.v1beta1.QueryVotesRequest) - - [QueryVotesResponse](#zgc.committee.v1beta1.QueryVotesResponse) +- [kava/cdp/v1beta1/genesis.proto](#kava/cdp/v1beta1/genesis.proto) + - [CollateralParam](#kava.cdp.v1beta1.CollateralParam) + - [DebtParam](#kava.cdp.v1beta1.DebtParam) + - [GenesisAccumulationTime](#kava.cdp.v1beta1.GenesisAccumulationTime) + - [GenesisState](#kava.cdp.v1beta1.GenesisState) + - [GenesisTotalPrincipal](#kava.cdp.v1beta1.GenesisTotalPrincipal) + - [Params](#kava.cdp.v1beta1.Params) - - [Query](#zgc.committee.v1beta1.Query) +- [kava/cdp/v1beta1/query.proto](#kava/cdp/v1beta1/query.proto) + - [CDPResponse](#kava.cdp.v1beta1.CDPResponse) + - [QueryAccountsRequest](#kava.cdp.v1beta1.QueryAccountsRequest) + - [QueryAccountsResponse](#kava.cdp.v1beta1.QueryAccountsResponse) + - [QueryCdpRequest](#kava.cdp.v1beta1.QueryCdpRequest) + - [QueryCdpResponse](#kava.cdp.v1beta1.QueryCdpResponse) + - [QueryCdpsRequest](#kava.cdp.v1beta1.QueryCdpsRequest) + - [QueryCdpsResponse](#kava.cdp.v1beta1.QueryCdpsResponse) + - [QueryDepositsRequest](#kava.cdp.v1beta1.QueryDepositsRequest) + - [QueryDepositsResponse](#kava.cdp.v1beta1.QueryDepositsResponse) + - [QueryParamsRequest](#kava.cdp.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#kava.cdp.v1beta1.QueryParamsResponse) + - [QueryTotalCollateralRequest](#kava.cdp.v1beta1.QueryTotalCollateralRequest) + - [QueryTotalCollateralResponse](#kava.cdp.v1beta1.QueryTotalCollateralResponse) + - [QueryTotalPrincipalRequest](#kava.cdp.v1beta1.QueryTotalPrincipalRequest) + - [QueryTotalPrincipalResponse](#kava.cdp.v1beta1.QueryTotalPrincipalResponse) -- [zgc/committee/v1beta1/tx.proto](#zgc/committee/v1beta1/tx.proto) - - [MsgSubmitProposal](#zgc.committee.v1beta1.MsgSubmitProposal) - - [MsgSubmitProposalResponse](#zgc.committee.v1beta1.MsgSubmitProposalResponse) - - [MsgVote](#zgc.committee.v1beta1.MsgVote) - - [MsgVoteResponse](#zgc.committee.v1beta1.MsgVoteResponse) + - [Query](#kava.cdp.v1beta1.Query) - - [Msg](#zgc.committee.v1beta1.Msg) +- [kava/cdp/v1beta1/tx.proto](#kava/cdp/v1beta1/tx.proto) + - [MsgCreateCDP](#kava.cdp.v1beta1.MsgCreateCDP) + - [MsgCreateCDPResponse](#kava.cdp.v1beta1.MsgCreateCDPResponse) + - [MsgDeposit](#kava.cdp.v1beta1.MsgDeposit) + - [MsgDepositResponse](#kava.cdp.v1beta1.MsgDepositResponse) + - [MsgDrawDebt](#kava.cdp.v1beta1.MsgDrawDebt) + - [MsgDrawDebtResponse](#kava.cdp.v1beta1.MsgDrawDebtResponse) + - [MsgLiquidate](#kava.cdp.v1beta1.MsgLiquidate) + - [MsgLiquidateResponse](#kava.cdp.v1beta1.MsgLiquidateResponse) + - [MsgRepayDebt](#kava.cdp.v1beta1.MsgRepayDebt) + - [MsgRepayDebtResponse](#kava.cdp.v1beta1.MsgRepayDebtResponse) + - [MsgWithdraw](#kava.cdp.v1beta1.MsgWithdraw) + - [MsgWithdrawResponse](#kava.cdp.v1beta1.MsgWithdrawResponse) -- [zgc/council/v1/genesis.proto](#zgc/council/v1/genesis.proto) - - [Ballot](#zgc.council.v1.Ballot) - - [Council](#zgc.council.v1.Council) - - [GenesisState](#zgc.council.v1.GenesisState) - - [Params](#zgc.council.v1.Params) - - [Vote](#zgc.council.v1.Vote) + - [Msg](#kava.cdp.v1beta1.Msg) -- [zgc/council/v1/query.proto](#zgc/council/v1/query.proto) - - [QueryCurrentCouncilIDRequest](#zgc.council.v1.QueryCurrentCouncilIDRequest) - - [QueryCurrentCouncilIDResponse](#zgc.council.v1.QueryCurrentCouncilIDResponse) - - [QueryRegisteredVotersRequest](#zgc.council.v1.QueryRegisteredVotersRequest) - - [QueryRegisteredVotersResponse](#zgc.council.v1.QueryRegisteredVotersResponse) +- [kava/committee/v1beta1/committee.proto](#kava/committee/v1beta1/committee.proto) + - [BaseCommittee](#kava.committee.v1beta1.BaseCommittee) + - [MemberCommittee](#kava.committee.v1beta1.MemberCommittee) + - [TokenCommittee](#kava.committee.v1beta1.TokenCommittee) - - [Query](#zgc.council.v1.Query) + - [TallyOption](#kava.committee.v1beta1.TallyOption) -- [zgc/council/v1/tx.proto](#zgc/council/v1/tx.proto) - - [MsgRegister](#zgc.council.v1.MsgRegister) - - [MsgRegisterResponse](#zgc.council.v1.MsgRegisterResponse) - - [MsgVote](#zgc.council.v1.MsgVote) - - [MsgVoteResponse](#zgc.council.v1.MsgVoteResponse) +- [kava/committee/v1beta1/genesis.proto](#kava/committee/v1beta1/genesis.proto) + - [GenesisState](#kava.committee.v1beta1.GenesisState) + - [Proposal](#kava.committee.v1beta1.Proposal) + - [Vote](#kava.committee.v1beta1.Vote) - - [Msg](#zgc.council.v1.Msg) + - [VoteType](#kava.committee.v1beta1.VoteType) -- [zgc/dasigners/v1/dasigners.proto](#zgc/dasigners/v1/dasigners.proto) - - [Quorum](#zgc.dasigners.v1.Quorum) - - [Quorums](#zgc.dasigners.v1.Quorums) - - [Signer](#zgc.dasigners.v1.Signer) +- [kava/committee/v1beta1/permissions.proto](#kava/committee/v1beta1/permissions.proto) + - [AllowedParamsChange](#kava.committee.v1beta1.AllowedParamsChange) + - [CommunityCDPRepayDebtPermission](#kava.committee.v1beta1.CommunityCDPRepayDebtPermission) + - [CommunityCDPWithdrawCollateralPermission](#kava.committee.v1beta1.CommunityCDPWithdrawCollateralPermission) + - [CommunityPoolLendWithdrawPermission](#kava.committee.v1beta1.CommunityPoolLendWithdrawPermission) + - [GodPermission](#kava.committee.v1beta1.GodPermission) + - [ParamsChangePermission](#kava.committee.v1beta1.ParamsChangePermission) + - [SoftwareUpgradePermission](#kava.committee.v1beta1.SoftwareUpgradePermission) + - [SubparamRequirement](#kava.committee.v1beta1.SubparamRequirement) + - [TextPermission](#kava.committee.v1beta1.TextPermission) -- [zgc/dasigners/v1/genesis.proto](#zgc/dasigners/v1/genesis.proto) - - [GenesisState](#zgc.dasigners.v1.GenesisState) - - [Params](#zgc.dasigners.v1.Params) +- [kava/committee/v1beta1/proposal.proto](#kava/committee/v1beta1/proposal.proto) + - [CommitteeChangeProposal](#kava.committee.v1beta1.CommitteeChangeProposal) + - [CommitteeDeleteProposal](#kava.committee.v1beta1.CommitteeDeleteProposal) -- [zgc/dasigners/v1/query.proto](#zgc/dasigners/v1/query.proto) - - [QueryAggregatePubkeyG1Request](#zgc.dasigners.v1.QueryAggregatePubkeyG1Request) - - [QueryAggregatePubkeyG1Response](#zgc.dasigners.v1.QueryAggregatePubkeyG1Response) - - [QueryEpochNumberRequest](#zgc.dasigners.v1.QueryEpochNumberRequest) - - [QueryEpochNumberResponse](#zgc.dasigners.v1.QueryEpochNumberResponse) - - [QueryEpochQuorumRequest](#zgc.dasigners.v1.QueryEpochQuorumRequest) - - [QueryEpochQuorumResponse](#zgc.dasigners.v1.QueryEpochQuorumResponse) - - [QueryEpochQuorumRowRequest](#zgc.dasigners.v1.QueryEpochQuorumRowRequest) - - [QueryEpochQuorumRowResponse](#zgc.dasigners.v1.QueryEpochQuorumRowResponse) - - [QueryQuorumCountRequest](#zgc.dasigners.v1.QueryQuorumCountRequest) - - [QueryQuorumCountResponse](#zgc.dasigners.v1.QueryQuorumCountResponse) - - [QuerySignerRequest](#zgc.dasigners.v1.QuerySignerRequest) - - [QuerySignerResponse](#zgc.dasigners.v1.QuerySignerResponse) +- [kava/committee/v1beta1/query.proto](#kava/committee/v1beta1/query.proto) + - [QueryCommitteeRequest](#kava.committee.v1beta1.QueryCommitteeRequest) + - [QueryCommitteeResponse](#kava.committee.v1beta1.QueryCommitteeResponse) + - [QueryCommitteesRequest](#kava.committee.v1beta1.QueryCommitteesRequest) + - [QueryCommitteesResponse](#kava.committee.v1beta1.QueryCommitteesResponse) + - [QueryNextProposalIDRequest](#kava.committee.v1beta1.QueryNextProposalIDRequest) + - [QueryNextProposalIDResponse](#kava.committee.v1beta1.QueryNextProposalIDResponse) + - [QueryProposalRequest](#kava.committee.v1beta1.QueryProposalRequest) + - [QueryProposalResponse](#kava.committee.v1beta1.QueryProposalResponse) + - [QueryProposalsRequest](#kava.committee.v1beta1.QueryProposalsRequest) + - [QueryProposalsResponse](#kava.committee.v1beta1.QueryProposalsResponse) + - [QueryRawParamsRequest](#kava.committee.v1beta1.QueryRawParamsRequest) + - [QueryRawParamsResponse](#kava.committee.v1beta1.QueryRawParamsResponse) + - [QueryTallyRequest](#kava.committee.v1beta1.QueryTallyRequest) + - [QueryTallyResponse](#kava.committee.v1beta1.QueryTallyResponse) + - [QueryVoteRequest](#kava.committee.v1beta1.QueryVoteRequest) + - [QueryVoteResponse](#kava.committee.v1beta1.QueryVoteResponse) + - [QueryVotesRequest](#kava.committee.v1beta1.QueryVotesRequest) + - [QueryVotesResponse](#kava.committee.v1beta1.QueryVotesResponse) - - [Query](#zgc.dasigners.v1.Query) + - [Query](#kava.committee.v1beta1.Query) -- [zgc/dasigners/v1/tx.proto](#zgc/dasigners/v1/tx.proto) - - [MsgRegisterNextEpoch](#zgc.dasigners.v1.MsgRegisterNextEpoch) - - [MsgRegisterNextEpochResponse](#zgc.dasigners.v1.MsgRegisterNextEpochResponse) - - [MsgRegisterSigner](#zgc.dasigners.v1.MsgRegisterSigner) - - [MsgRegisterSignerResponse](#zgc.dasigners.v1.MsgRegisterSignerResponse) - - [MsgUpdateSocket](#zgc.dasigners.v1.MsgUpdateSocket) - - [MsgUpdateSocketResponse](#zgc.dasigners.v1.MsgUpdateSocketResponse) +- [kava/committee/v1beta1/tx.proto](#kava/committee/v1beta1/tx.proto) + - [MsgSubmitProposal](#kava.committee.v1beta1.MsgSubmitProposal) + - [MsgSubmitProposalResponse](#kava.committee.v1beta1.MsgSubmitProposalResponse) + - [MsgVote](#kava.committee.v1beta1.MsgVote) + - [MsgVoteResponse](#kava.committee.v1beta1.MsgVoteResponse) - - [Msg](#zgc.dasigners.v1.Msg) + - [Msg](#kava.committee.v1beta1.Msg) -- [zgc/evmutil/v1beta1/conversion_pair.proto](#zgc/evmutil/v1beta1/conversion_pair.proto) - - [AllowedCosmosCoinERC20Token](#zgc.evmutil.v1beta1.AllowedCosmosCoinERC20Token) - - [ConversionPair](#zgc.evmutil.v1beta1.ConversionPair) +- [kava/community/v1beta1/params.proto](#kava/community/v1beta1/params.proto) + - [Params](#kava.community.v1beta1.Params) -- [zgc/evmutil/v1beta1/genesis.proto](#zgc/evmutil/v1beta1/genesis.proto) - - [Account](#zgc.evmutil.v1beta1.Account) - - [GenesisState](#zgc.evmutil.v1beta1.GenesisState) - - [Params](#zgc.evmutil.v1beta1.Params) +- [kava/community/v1beta1/staking.proto](#kava/community/v1beta1/staking.proto) + - [StakingRewardsState](#kava.community.v1beta1.StakingRewardsState) -- [zgc/evmutil/v1beta1/query.proto](#zgc/evmutil/v1beta1/query.proto) - - [DeployedCosmosCoinContract](#zgc.evmutil.v1beta1.DeployedCosmosCoinContract) - - [QueryDeployedCosmosCoinContractsRequest](#zgc.evmutil.v1beta1.QueryDeployedCosmosCoinContractsRequest) - - [QueryDeployedCosmosCoinContractsResponse](#zgc.evmutil.v1beta1.QueryDeployedCosmosCoinContractsResponse) - - [QueryParamsRequest](#zgc.evmutil.v1beta1.QueryParamsRequest) - - [QueryParamsResponse](#zgc.evmutil.v1beta1.QueryParamsResponse) +- [kava/community/v1beta1/genesis.proto](#kava/community/v1beta1/genesis.proto) + - [GenesisState](#kava.community.v1beta1.GenesisState) - - [Query](#zgc.evmutil.v1beta1.Query) +- [kava/community/v1beta1/proposal.proto](#kava/community/v1beta1/proposal.proto) + - [CommunityCDPRepayDebtProposal](#kava.community.v1beta1.CommunityCDPRepayDebtProposal) + - [CommunityCDPWithdrawCollateralProposal](#kava.community.v1beta1.CommunityCDPWithdrawCollateralProposal) + - [CommunityPoolLendDepositProposal](#kava.community.v1beta1.CommunityPoolLendDepositProposal) + - [CommunityPoolLendWithdrawProposal](#kava.community.v1beta1.CommunityPoolLendWithdrawProposal) -- [zgc/evmutil/v1beta1/tx.proto](#zgc/evmutil/v1beta1/tx.proto) - - [MsgConvertCoinToERC20](#zgc.evmutil.v1beta1.MsgConvertCoinToERC20) - - [MsgConvertCoinToERC20Response](#zgc.evmutil.v1beta1.MsgConvertCoinToERC20Response) - - [MsgConvertCosmosCoinFromERC20](#zgc.evmutil.v1beta1.MsgConvertCosmosCoinFromERC20) - - [MsgConvertCosmosCoinFromERC20Response](#zgc.evmutil.v1beta1.MsgConvertCosmosCoinFromERC20Response) - - [MsgConvertCosmosCoinToERC20](#zgc.evmutil.v1beta1.MsgConvertCosmosCoinToERC20) - - [MsgConvertCosmosCoinToERC20Response](#zgc.evmutil.v1beta1.MsgConvertCosmosCoinToERC20Response) - - [MsgConvertERC20ToCoin](#zgc.evmutil.v1beta1.MsgConvertERC20ToCoin) - - [MsgConvertERC20ToCoinResponse](#zgc.evmutil.v1beta1.MsgConvertERC20ToCoinResponse) +- [kava/community/v1beta1/query.proto](#kava/community/v1beta1/query.proto) + - [QueryAnnualizedRewardsRequest](#kava.community.v1beta1.QueryAnnualizedRewardsRequest) + - [QueryAnnualizedRewardsResponse](#kava.community.v1beta1.QueryAnnualizedRewardsResponse) + - [QueryBalanceRequest](#kava.community.v1beta1.QueryBalanceRequest) + - [QueryBalanceResponse](#kava.community.v1beta1.QueryBalanceResponse) + - [QueryParamsRequest](#kava.community.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#kava.community.v1beta1.QueryParamsResponse) + - [QueryTotalBalanceRequest](#kava.community.v1beta1.QueryTotalBalanceRequest) + - [QueryTotalBalanceResponse](#kava.community.v1beta1.QueryTotalBalanceResponse) - - [Msg](#zgc.evmutil.v1beta1.Msg) + - [Query](#kava.community.v1beta1.Query) -- [zgc/issuance/v1beta1/genesis.proto](#zgc/issuance/v1beta1/genesis.proto) - - [Asset](#zgc.issuance.v1beta1.Asset) - - [AssetSupply](#zgc.issuance.v1beta1.AssetSupply) - - [GenesisState](#zgc.issuance.v1beta1.GenesisState) - - [Params](#zgc.issuance.v1beta1.Params) - - [RateLimit](#zgc.issuance.v1beta1.RateLimit) +- [kava/community/v1beta1/tx.proto](#kava/community/v1beta1/tx.proto) + - [MsgFundCommunityPool](#kava.community.v1beta1.MsgFundCommunityPool) + - [MsgFundCommunityPoolResponse](#kava.community.v1beta1.MsgFundCommunityPoolResponse) + - [MsgUpdateParams](#kava.community.v1beta1.MsgUpdateParams) + - [MsgUpdateParamsResponse](#kava.community.v1beta1.MsgUpdateParamsResponse) -- [zgc/issuance/v1beta1/query.proto](#zgc/issuance/v1beta1/query.proto) - - [QueryParamsRequest](#zgc.issuance.v1beta1.QueryParamsRequest) - - [QueryParamsResponse](#zgc.issuance.v1beta1.QueryParamsResponse) + - [Msg](#kava.community.v1beta1.Msg) - - [Query](#zgc.issuance.v1beta1.Query) +- [kava/earn/v1beta1/strategy.proto](#kava/earn/v1beta1/strategy.proto) + - [StrategyType](#kava.earn.v1beta1.StrategyType) -- [zgc/issuance/v1beta1/tx.proto](#zgc/issuance/v1beta1/tx.proto) - - [MsgBlockAddress](#zgc.issuance.v1beta1.MsgBlockAddress) - - [MsgBlockAddressResponse](#zgc.issuance.v1beta1.MsgBlockAddressResponse) - - [MsgIssueTokens](#zgc.issuance.v1beta1.MsgIssueTokens) - - [MsgIssueTokensResponse](#zgc.issuance.v1beta1.MsgIssueTokensResponse) - - [MsgRedeemTokens](#zgc.issuance.v1beta1.MsgRedeemTokens) - - [MsgRedeemTokensResponse](#zgc.issuance.v1beta1.MsgRedeemTokensResponse) - - [MsgSetPauseStatus](#zgc.issuance.v1beta1.MsgSetPauseStatus) - - [MsgSetPauseStatusResponse](#zgc.issuance.v1beta1.MsgSetPauseStatusResponse) - - [MsgUnblockAddress](#zgc.issuance.v1beta1.MsgUnblockAddress) - - [MsgUnblockAddressResponse](#zgc.issuance.v1beta1.MsgUnblockAddressResponse) +- [kava/earn/v1beta1/vault.proto](#kava/earn/v1beta1/vault.proto) + - [AllowedVault](#kava.earn.v1beta1.AllowedVault) + - [VaultRecord](#kava.earn.v1beta1.VaultRecord) + - [VaultShare](#kava.earn.v1beta1.VaultShare) + - [VaultShareRecord](#kava.earn.v1beta1.VaultShareRecord) - - [Msg](#zgc.issuance.v1beta1.Msg) +- [kava/earn/v1beta1/params.proto](#kava/earn/v1beta1/params.proto) + - [Params](#kava.earn.v1beta1.Params) -- [zgc/pricefeed/v1beta1/store.proto](#zgc/pricefeed/v1beta1/store.proto) - - [CurrentPrice](#zgc.pricefeed.v1beta1.CurrentPrice) - - [Market](#zgc.pricefeed.v1beta1.Market) - - [Params](#zgc.pricefeed.v1beta1.Params) - - [PostedPrice](#zgc.pricefeed.v1beta1.PostedPrice) +- [kava/earn/v1beta1/genesis.proto](#kava/earn/v1beta1/genesis.proto) + - [GenesisState](#kava.earn.v1beta1.GenesisState) -- [zgc/pricefeed/v1beta1/genesis.proto](#zgc/pricefeed/v1beta1/genesis.proto) - - [GenesisState](#zgc.pricefeed.v1beta1.GenesisState) +- [kava/earn/v1beta1/proposal.proto](#kava/earn/v1beta1/proposal.proto) + - [CommunityPoolDepositProposal](#kava.earn.v1beta1.CommunityPoolDepositProposal) + - [CommunityPoolDepositProposalJSON](#kava.earn.v1beta1.CommunityPoolDepositProposalJSON) + - [CommunityPoolWithdrawProposal](#kava.earn.v1beta1.CommunityPoolWithdrawProposal) + - [CommunityPoolWithdrawProposalJSON](#kava.earn.v1beta1.CommunityPoolWithdrawProposalJSON) -- [zgc/pricefeed/v1beta1/query.proto](#zgc/pricefeed/v1beta1/query.proto) - - [CurrentPriceResponse](#zgc.pricefeed.v1beta1.CurrentPriceResponse) - - [MarketResponse](#zgc.pricefeed.v1beta1.MarketResponse) - - [PostedPriceResponse](#zgc.pricefeed.v1beta1.PostedPriceResponse) - - [QueryMarketsRequest](#zgc.pricefeed.v1beta1.QueryMarketsRequest) - - [QueryMarketsResponse](#zgc.pricefeed.v1beta1.QueryMarketsResponse) - - [QueryOraclesRequest](#zgc.pricefeed.v1beta1.QueryOraclesRequest) - - [QueryOraclesResponse](#zgc.pricefeed.v1beta1.QueryOraclesResponse) - - [QueryParamsRequest](#zgc.pricefeed.v1beta1.QueryParamsRequest) - - [QueryParamsResponse](#zgc.pricefeed.v1beta1.QueryParamsResponse) - - [QueryPriceRequest](#zgc.pricefeed.v1beta1.QueryPriceRequest) - - [QueryPriceResponse](#zgc.pricefeed.v1beta1.QueryPriceResponse) - - [QueryPricesRequest](#zgc.pricefeed.v1beta1.QueryPricesRequest) - - [QueryPricesResponse](#zgc.pricefeed.v1beta1.QueryPricesResponse) - - [QueryRawPricesRequest](#zgc.pricefeed.v1beta1.QueryRawPricesRequest) - - [QueryRawPricesResponse](#zgc.pricefeed.v1beta1.QueryRawPricesResponse) +- [kava/earn/v1beta1/query.proto](#kava/earn/v1beta1/query.proto) + - [DepositResponse](#kava.earn.v1beta1.DepositResponse) + - [QueryDepositsRequest](#kava.earn.v1beta1.QueryDepositsRequest) + - [QueryDepositsResponse](#kava.earn.v1beta1.QueryDepositsResponse) + - [QueryParamsRequest](#kava.earn.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#kava.earn.v1beta1.QueryParamsResponse) + - [QueryTotalSupplyRequest](#kava.earn.v1beta1.QueryTotalSupplyRequest) + - [QueryTotalSupplyResponse](#kava.earn.v1beta1.QueryTotalSupplyResponse) + - [QueryVaultRequest](#kava.earn.v1beta1.QueryVaultRequest) + - [QueryVaultResponse](#kava.earn.v1beta1.QueryVaultResponse) + - [QueryVaultsRequest](#kava.earn.v1beta1.QueryVaultsRequest) + - [QueryVaultsResponse](#kava.earn.v1beta1.QueryVaultsResponse) + - [VaultResponse](#kava.earn.v1beta1.VaultResponse) - - [Query](#zgc.pricefeed.v1beta1.Query) + - [Query](#kava.earn.v1beta1.Query) -- [zgc/pricefeed/v1beta1/tx.proto](#zgc/pricefeed/v1beta1/tx.proto) - - [MsgPostPrice](#zgc.pricefeed.v1beta1.MsgPostPrice) - - [MsgPostPriceResponse](#zgc.pricefeed.v1beta1.MsgPostPriceResponse) +- [kava/earn/v1beta1/tx.proto](#kava/earn/v1beta1/tx.proto) + - [MsgDeposit](#kava.earn.v1beta1.MsgDeposit) + - [MsgDepositResponse](#kava.earn.v1beta1.MsgDepositResponse) + - [MsgWithdraw](#kava.earn.v1beta1.MsgWithdraw) + - [MsgWithdrawResponse](#kava.earn.v1beta1.MsgWithdrawResponse) - - [Msg](#zgc.pricefeed.v1beta1.Msg) + - [Msg](#kava.earn.v1beta1.Msg) + +- [kava/evmutil/v1beta1/conversion_pair.proto](#kava/evmutil/v1beta1/conversion_pair.proto) + - [AllowedCosmosCoinERC20Token](#kava.evmutil.v1beta1.AllowedCosmosCoinERC20Token) + - [ConversionPair](#kava.evmutil.v1beta1.ConversionPair) + +- [kava/evmutil/v1beta1/genesis.proto](#kava/evmutil/v1beta1/genesis.proto) + - [Account](#kava.evmutil.v1beta1.Account) + - [GenesisState](#kava.evmutil.v1beta1.GenesisState) + - [Params](#kava.evmutil.v1beta1.Params) + +- [kava/evmutil/v1beta1/query.proto](#kava/evmutil/v1beta1/query.proto) + - [DeployedCosmosCoinContract](#kava.evmutil.v1beta1.DeployedCosmosCoinContract) + - [QueryDeployedCosmosCoinContractsRequest](#kava.evmutil.v1beta1.QueryDeployedCosmosCoinContractsRequest) + - [QueryDeployedCosmosCoinContractsResponse](#kava.evmutil.v1beta1.QueryDeployedCosmosCoinContractsResponse) + - [QueryParamsRequest](#kava.evmutil.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#kava.evmutil.v1beta1.QueryParamsResponse) + + - [Query](#kava.evmutil.v1beta1.Query) + +- [kava/evmutil/v1beta1/tx.proto](#kava/evmutil/v1beta1/tx.proto) + - [MsgConvertCoinToERC20](#kava.evmutil.v1beta1.MsgConvertCoinToERC20) + - [MsgConvertCoinToERC20Response](#kava.evmutil.v1beta1.MsgConvertCoinToERC20Response) + - [MsgConvertCosmosCoinFromERC20](#kava.evmutil.v1beta1.MsgConvertCosmosCoinFromERC20) + - [MsgConvertCosmosCoinFromERC20Response](#kava.evmutil.v1beta1.MsgConvertCosmosCoinFromERC20Response) + - [MsgConvertCosmosCoinToERC20](#kava.evmutil.v1beta1.MsgConvertCosmosCoinToERC20) + - [MsgConvertCosmosCoinToERC20Response](#kava.evmutil.v1beta1.MsgConvertCosmosCoinToERC20Response) + - [MsgConvertERC20ToCoin](#kava.evmutil.v1beta1.MsgConvertERC20ToCoin) + - [MsgConvertERC20ToCoinResponse](#kava.evmutil.v1beta1.MsgConvertERC20ToCoinResponse) + + - [Msg](#kava.evmutil.v1beta1.Msg) + +- [kava/hard/v1beta1/hard.proto](#kava/hard/v1beta1/hard.proto) + - [Borrow](#kava.hard.v1beta1.Borrow) + - [BorrowInterestFactor](#kava.hard.v1beta1.BorrowInterestFactor) + - [BorrowLimit](#kava.hard.v1beta1.BorrowLimit) + - [CoinsProto](#kava.hard.v1beta1.CoinsProto) + - [Deposit](#kava.hard.v1beta1.Deposit) + - [InterestRateModel](#kava.hard.v1beta1.InterestRateModel) + - [MoneyMarket](#kava.hard.v1beta1.MoneyMarket) + - [Params](#kava.hard.v1beta1.Params) + - [SupplyInterestFactor](#kava.hard.v1beta1.SupplyInterestFactor) + +- [kava/hard/v1beta1/genesis.proto](#kava/hard/v1beta1/genesis.proto) + - [GenesisAccumulationTime](#kava.hard.v1beta1.GenesisAccumulationTime) + - [GenesisState](#kava.hard.v1beta1.GenesisState) + +- [kava/hard/v1beta1/query.proto](#kava/hard/v1beta1/query.proto) + - [BorrowInterestFactorResponse](#kava.hard.v1beta1.BorrowInterestFactorResponse) + - [BorrowResponse](#kava.hard.v1beta1.BorrowResponse) + - [DepositResponse](#kava.hard.v1beta1.DepositResponse) + - [InterestFactor](#kava.hard.v1beta1.InterestFactor) + - [MoneyMarketInterestRate](#kava.hard.v1beta1.MoneyMarketInterestRate) + - [QueryAccountsRequest](#kava.hard.v1beta1.QueryAccountsRequest) + - [QueryAccountsResponse](#kava.hard.v1beta1.QueryAccountsResponse) + - [QueryBorrowsRequest](#kava.hard.v1beta1.QueryBorrowsRequest) + - [QueryBorrowsResponse](#kava.hard.v1beta1.QueryBorrowsResponse) + - [QueryDepositsRequest](#kava.hard.v1beta1.QueryDepositsRequest) + - [QueryDepositsResponse](#kava.hard.v1beta1.QueryDepositsResponse) + - [QueryInterestFactorsRequest](#kava.hard.v1beta1.QueryInterestFactorsRequest) + - [QueryInterestFactorsResponse](#kava.hard.v1beta1.QueryInterestFactorsResponse) + - [QueryInterestRateRequest](#kava.hard.v1beta1.QueryInterestRateRequest) + - [QueryInterestRateResponse](#kava.hard.v1beta1.QueryInterestRateResponse) + - [QueryParamsRequest](#kava.hard.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#kava.hard.v1beta1.QueryParamsResponse) + - [QueryReservesRequest](#kava.hard.v1beta1.QueryReservesRequest) + - [QueryReservesResponse](#kava.hard.v1beta1.QueryReservesResponse) + - [QueryTotalBorrowedRequest](#kava.hard.v1beta1.QueryTotalBorrowedRequest) + - [QueryTotalBorrowedResponse](#kava.hard.v1beta1.QueryTotalBorrowedResponse) + - [QueryTotalDepositedRequest](#kava.hard.v1beta1.QueryTotalDepositedRequest) + - [QueryTotalDepositedResponse](#kava.hard.v1beta1.QueryTotalDepositedResponse) + - [QueryUnsyncedBorrowsRequest](#kava.hard.v1beta1.QueryUnsyncedBorrowsRequest) + - [QueryUnsyncedBorrowsResponse](#kava.hard.v1beta1.QueryUnsyncedBorrowsResponse) + - [QueryUnsyncedDepositsRequest](#kava.hard.v1beta1.QueryUnsyncedDepositsRequest) + - [QueryUnsyncedDepositsResponse](#kava.hard.v1beta1.QueryUnsyncedDepositsResponse) + - [SupplyInterestFactorResponse](#kava.hard.v1beta1.SupplyInterestFactorResponse) + + - [Query](#kava.hard.v1beta1.Query) + +- [kava/hard/v1beta1/tx.proto](#kava/hard/v1beta1/tx.proto) + - [MsgBorrow](#kava.hard.v1beta1.MsgBorrow) + - [MsgBorrowResponse](#kava.hard.v1beta1.MsgBorrowResponse) + - [MsgDeposit](#kava.hard.v1beta1.MsgDeposit) + - [MsgDepositResponse](#kava.hard.v1beta1.MsgDepositResponse) + - [MsgLiquidate](#kava.hard.v1beta1.MsgLiquidate) + - [MsgLiquidateResponse](#kava.hard.v1beta1.MsgLiquidateResponse) + - [MsgRepay](#kava.hard.v1beta1.MsgRepay) + - [MsgRepayResponse](#kava.hard.v1beta1.MsgRepayResponse) + - [MsgWithdraw](#kava.hard.v1beta1.MsgWithdraw) + - [MsgWithdrawResponse](#kava.hard.v1beta1.MsgWithdrawResponse) + + - [Msg](#kava.hard.v1beta1.Msg) + +- [kava/incentive/v1beta1/apy.proto](#kava/incentive/v1beta1/apy.proto) + - [Apy](#kava.incentive.v1beta1.Apy) + +- [kava/incentive/v1beta1/claims.proto](#kava/incentive/v1beta1/claims.proto) + - [BaseClaim](#kava.incentive.v1beta1.BaseClaim) + - [BaseMultiClaim](#kava.incentive.v1beta1.BaseMultiClaim) + - [DelegatorClaim](#kava.incentive.v1beta1.DelegatorClaim) + - [EarnClaim](#kava.incentive.v1beta1.EarnClaim) + - [HardLiquidityProviderClaim](#kava.incentive.v1beta1.HardLiquidityProviderClaim) + - [MultiRewardIndex](#kava.incentive.v1beta1.MultiRewardIndex) + - [MultiRewardIndexesProto](#kava.incentive.v1beta1.MultiRewardIndexesProto) + - [RewardIndex](#kava.incentive.v1beta1.RewardIndex) + - [RewardIndexesProto](#kava.incentive.v1beta1.RewardIndexesProto) + - [SavingsClaim](#kava.incentive.v1beta1.SavingsClaim) + - [SwapClaim](#kava.incentive.v1beta1.SwapClaim) + - [USDXMintingClaim](#kava.incentive.v1beta1.USDXMintingClaim) + +- [kava/incentive/v1beta1/params.proto](#kava/incentive/v1beta1/params.proto) + - [MultiRewardPeriod](#kava.incentive.v1beta1.MultiRewardPeriod) + - [Multiplier](#kava.incentive.v1beta1.Multiplier) + - [MultipliersPerDenom](#kava.incentive.v1beta1.MultipliersPerDenom) + - [Params](#kava.incentive.v1beta1.Params) + - [RewardPeriod](#kava.incentive.v1beta1.RewardPeriod) + +- [kava/incentive/v1beta1/genesis.proto](#kava/incentive/v1beta1/genesis.proto) + - [AccumulationTime](#kava.incentive.v1beta1.AccumulationTime) + - [GenesisRewardState](#kava.incentive.v1beta1.GenesisRewardState) + - [GenesisState](#kava.incentive.v1beta1.GenesisState) + +- [kava/incentive/v1beta1/query.proto](#kava/incentive/v1beta1/query.proto) + - [QueryApyRequest](#kava.incentive.v1beta1.QueryApyRequest) + - [QueryApyResponse](#kava.incentive.v1beta1.QueryApyResponse) + - [QueryParamsRequest](#kava.incentive.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#kava.incentive.v1beta1.QueryParamsResponse) + - [QueryRewardFactorsRequest](#kava.incentive.v1beta1.QueryRewardFactorsRequest) + - [QueryRewardFactorsResponse](#kava.incentive.v1beta1.QueryRewardFactorsResponse) + - [QueryRewardsRequest](#kava.incentive.v1beta1.QueryRewardsRequest) + - [QueryRewardsResponse](#kava.incentive.v1beta1.QueryRewardsResponse) + + - [Query](#kava.incentive.v1beta1.Query) + +- [kava/incentive/v1beta1/tx.proto](#kava/incentive/v1beta1/tx.proto) + - [MsgClaimDelegatorReward](#kava.incentive.v1beta1.MsgClaimDelegatorReward) + - [MsgClaimDelegatorRewardResponse](#kava.incentive.v1beta1.MsgClaimDelegatorRewardResponse) + - [MsgClaimEarnReward](#kava.incentive.v1beta1.MsgClaimEarnReward) + - [MsgClaimEarnRewardResponse](#kava.incentive.v1beta1.MsgClaimEarnRewardResponse) + - [MsgClaimHardReward](#kava.incentive.v1beta1.MsgClaimHardReward) + - [MsgClaimHardRewardResponse](#kava.incentive.v1beta1.MsgClaimHardRewardResponse) + - [MsgClaimSavingsReward](#kava.incentive.v1beta1.MsgClaimSavingsReward) + - [MsgClaimSavingsRewardResponse](#kava.incentive.v1beta1.MsgClaimSavingsRewardResponse) + - [MsgClaimSwapReward](#kava.incentive.v1beta1.MsgClaimSwapReward) + - [MsgClaimSwapRewardResponse](#kava.incentive.v1beta1.MsgClaimSwapRewardResponse) + - [MsgClaimUSDXMintingReward](#kava.incentive.v1beta1.MsgClaimUSDXMintingReward) + - [MsgClaimUSDXMintingRewardResponse](#kava.incentive.v1beta1.MsgClaimUSDXMintingRewardResponse) + - [Selection](#kava.incentive.v1beta1.Selection) + + - [Msg](#kava.incentive.v1beta1.Msg) + +- [kava/issuance/v1beta1/genesis.proto](#kava/issuance/v1beta1/genesis.proto) + - [Asset](#kava.issuance.v1beta1.Asset) + - [AssetSupply](#kava.issuance.v1beta1.AssetSupply) + - [GenesisState](#kava.issuance.v1beta1.GenesisState) + - [Params](#kava.issuance.v1beta1.Params) + - [RateLimit](#kava.issuance.v1beta1.RateLimit) + +- [kava/issuance/v1beta1/query.proto](#kava/issuance/v1beta1/query.proto) + - [QueryParamsRequest](#kava.issuance.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#kava.issuance.v1beta1.QueryParamsResponse) + + - [Query](#kava.issuance.v1beta1.Query) + +- [kava/issuance/v1beta1/tx.proto](#kava/issuance/v1beta1/tx.proto) + - [MsgBlockAddress](#kava.issuance.v1beta1.MsgBlockAddress) + - [MsgBlockAddressResponse](#kava.issuance.v1beta1.MsgBlockAddressResponse) + - [MsgIssueTokens](#kava.issuance.v1beta1.MsgIssueTokens) + - [MsgIssueTokensResponse](#kava.issuance.v1beta1.MsgIssueTokensResponse) + - [MsgRedeemTokens](#kava.issuance.v1beta1.MsgRedeemTokens) + - [MsgRedeemTokensResponse](#kava.issuance.v1beta1.MsgRedeemTokensResponse) + - [MsgSetPauseStatus](#kava.issuance.v1beta1.MsgSetPauseStatus) + - [MsgSetPauseStatusResponse](#kava.issuance.v1beta1.MsgSetPauseStatusResponse) + - [MsgUnblockAddress](#kava.issuance.v1beta1.MsgUnblockAddress) + - [MsgUnblockAddressResponse](#kava.issuance.v1beta1.MsgUnblockAddressResponse) + + - [Msg](#kava.issuance.v1beta1.Msg) + +- [kava/kavadist/v1beta1/params.proto](#kava/kavadist/v1beta1/params.proto) + - [CoreReward](#kava.kavadist.v1beta1.CoreReward) + - [InfrastructureParams](#kava.kavadist.v1beta1.InfrastructureParams) + - [Params](#kava.kavadist.v1beta1.Params) + - [PartnerReward](#kava.kavadist.v1beta1.PartnerReward) + - [Period](#kava.kavadist.v1beta1.Period) + +- [kava/kavadist/v1beta1/genesis.proto](#kava/kavadist/v1beta1/genesis.proto) + - [GenesisState](#kava.kavadist.v1beta1.GenesisState) + +- [kava/kavadist/v1beta1/proposal.proto](#kava/kavadist/v1beta1/proposal.proto) + - [CommunityPoolMultiSpendProposal](#kava.kavadist.v1beta1.CommunityPoolMultiSpendProposal) + - [CommunityPoolMultiSpendProposalJSON](#kava.kavadist.v1beta1.CommunityPoolMultiSpendProposalJSON) + - [MultiSpendRecipient](#kava.kavadist.v1beta1.MultiSpendRecipient) + +- [kava/kavadist/v1beta1/query.proto](#kava/kavadist/v1beta1/query.proto) + - [QueryBalanceRequest](#kava.kavadist.v1beta1.QueryBalanceRequest) + - [QueryBalanceResponse](#kava.kavadist.v1beta1.QueryBalanceResponse) + - [QueryParamsRequest](#kava.kavadist.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#kava.kavadist.v1beta1.QueryParamsResponse) + + - [Query](#kava.kavadist.v1beta1.Query) + +- [kava/liquid/v1beta1/query.proto](#kava/liquid/v1beta1/query.proto) + - [QueryDelegatedBalanceRequest](#kava.liquid.v1beta1.QueryDelegatedBalanceRequest) + - [QueryDelegatedBalanceResponse](#kava.liquid.v1beta1.QueryDelegatedBalanceResponse) + - [QueryTotalSupplyRequest](#kava.liquid.v1beta1.QueryTotalSupplyRequest) + - [QueryTotalSupplyResponse](#kava.liquid.v1beta1.QueryTotalSupplyResponse) + + - [Query](#kava.liquid.v1beta1.Query) + +- [kava/liquid/v1beta1/tx.proto](#kava/liquid/v1beta1/tx.proto) + - [MsgBurnDerivative](#kava.liquid.v1beta1.MsgBurnDerivative) + - [MsgBurnDerivativeResponse](#kava.liquid.v1beta1.MsgBurnDerivativeResponse) + - [MsgMintDerivative](#kava.liquid.v1beta1.MsgMintDerivative) + - [MsgMintDerivativeResponse](#kava.liquid.v1beta1.MsgMintDerivativeResponse) + + - [Msg](#kava.liquid.v1beta1.Msg) + +- [kava/precisebank/v1/genesis.proto](#kava/precisebank/v1/genesis.proto) + - [FractionalBalance](#kava.precisebank.v1.FractionalBalance) + - [GenesisState](#kava.precisebank.v1.GenesisState) + +- [kava/precisebank/v1/query.proto](#kava/precisebank/v1/query.proto) + - [QueryFractionalBalanceRequest](#kava.precisebank.v1.QueryFractionalBalanceRequest) + - [QueryFractionalBalanceResponse](#kava.precisebank.v1.QueryFractionalBalanceResponse) + - [QueryRemainderRequest](#kava.precisebank.v1.QueryRemainderRequest) + - [QueryRemainderResponse](#kava.precisebank.v1.QueryRemainderResponse) + - [QueryTotalFractionalBalancesRequest](#kava.precisebank.v1.QueryTotalFractionalBalancesRequest) + - [QueryTotalFractionalBalancesResponse](#kava.precisebank.v1.QueryTotalFractionalBalancesResponse) + + - [Query](#kava.precisebank.v1.Query) + +- [kava/pricefeed/v1beta1/store.proto](#kava/pricefeed/v1beta1/store.proto) + - [CurrentPrice](#kava.pricefeed.v1beta1.CurrentPrice) + - [Market](#kava.pricefeed.v1beta1.Market) + - [Params](#kava.pricefeed.v1beta1.Params) + - [PostedPrice](#kava.pricefeed.v1beta1.PostedPrice) + +- [kava/pricefeed/v1beta1/genesis.proto](#kava/pricefeed/v1beta1/genesis.proto) + - [GenesisState](#kava.pricefeed.v1beta1.GenesisState) + +- [kava/pricefeed/v1beta1/query.proto](#kava/pricefeed/v1beta1/query.proto) + - [CurrentPriceResponse](#kava.pricefeed.v1beta1.CurrentPriceResponse) + - [MarketResponse](#kava.pricefeed.v1beta1.MarketResponse) + - [PostedPriceResponse](#kava.pricefeed.v1beta1.PostedPriceResponse) + - [QueryMarketsRequest](#kava.pricefeed.v1beta1.QueryMarketsRequest) + - [QueryMarketsResponse](#kava.pricefeed.v1beta1.QueryMarketsResponse) + - [QueryOraclesRequest](#kava.pricefeed.v1beta1.QueryOraclesRequest) + - [QueryOraclesResponse](#kava.pricefeed.v1beta1.QueryOraclesResponse) + - [QueryParamsRequest](#kava.pricefeed.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#kava.pricefeed.v1beta1.QueryParamsResponse) + - [QueryPriceRequest](#kava.pricefeed.v1beta1.QueryPriceRequest) + - [QueryPriceResponse](#kava.pricefeed.v1beta1.QueryPriceResponse) + - [QueryPricesRequest](#kava.pricefeed.v1beta1.QueryPricesRequest) + - [QueryPricesResponse](#kava.pricefeed.v1beta1.QueryPricesResponse) + - [QueryRawPricesRequest](#kava.pricefeed.v1beta1.QueryRawPricesRequest) + - [QueryRawPricesResponse](#kava.pricefeed.v1beta1.QueryRawPricesResponse) + + - [Query](#kava.pricefeed.v1beta1.Query) + +- [kava/pricefeed/v1beta1/tx.proto](#kava/pricefeed/v1beta1/tx.proto) + - [MsgPostPrice](#kava.pricefeed.v1beta1.MsgPostPrice) + - [MsgPostPriceResponse](#kava.pricefeed.v1beta1.MsgPostPriceResponse) + + - [Msg](#kava.pricefeed.v1beta1.Msg) + +- [kava/router/v1beta1/tx.proto](#kava/router/v1beta1/tx.proto) + - [MsgDelegateMintDeposit](#kava.router.v1beta1.MsgDelegateMintDeposit) + - [MsgDelegateMintDepositResponse](#kava.router.v1beta1.MsgDelegateMintDepositResponse) + - [MsgMintDeposit](#kava.router.v1beta1.MsgMintDeposit) + - [MsgMintDepositResponse](#kava.router.v1beta1.MsgMintDepositResponse) + - [MsgWithdrawBurn](#kava.router.v1beta1.MsgWithdrawBurn) + - [MsgWithdrawBurnResponse](#kava.router.v1beta1.MsgWithdrawBurnResponse) + - [MsgWithdrawBurnUndelegate](#kava.router.v1beta1.MsgWithdrawBurnUndelegate) + - [MsgWithdrawBurnUndelegateResponse](#kava.router.v1beta1.MsgWithdrawBurnUndelegateResponse) + + - [Msg](#kava.router.v1beta1.Msg) + +- [kava/savings/v1beta1/store.proto](#kava/savings/v1beta1/store.proto) + - [Deposit](#kava.savings.v1beta1.Deposit) + - [Params](#kava.savings.v1beta1.Params) + +- [kava/savings/v1beta1/genesis.proto](#kava/savings/v1beta1/genesis.proto) + - [GenesisState](#kava.savings.v1beta1.GenesisState) + +- [kava/savings/v1beta1/query.proto](#kava/savings/v1beta1/query.proto) + - [QueryDepositsRequest](#kava.savings.v1beta1.QueryDepositsRequest) + - [QueryDepositsResponse](#kava.savings.v1beta1.QueryDepositsResponse) + - [QueryParamsRequest](#kava.savings.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#kava.savings.v1beta1.QueryParamsResponse) + - [QueryTotalSupplyRequest](#kava.savings.v1beta1.QueryTotalSupplyRequest) + - [QueryTotalSupplyResponse](#kava.savings.v1beta1.QueryTotalSupplyResponse) + + - [Query](#kava.savings.v1beta1.Query) + +- [kava/savings/v1beta1/tx.proto](#kava/savings/v1beta1/tx.proto) + - [MsgDeposit](#kava.savings.v1beta1.MsgDeposit) + - [MsgDepositResponse](#kava.savings.v1beta1.MsgDepositResponse) + - [MsgWithdraw](#kava.savings.v1beta1.MsgWithdraw) + - [MsgWithdrawResponse](#kava.savings.v1beta1.MsgWithdrawResponse) + + - [Msg](#kava.savings.v1beta1.Msg) + +- [kava/swap/v1beta1/swap.proto](#kava/swap/v1beta1/swap.proto) + - [AllowedPool](#kava.swap.v1beta1.AllowedPool) + - [Params](#kava.swap.v1beta1.Params) + - [PoolRecord](#kava.swap.v1beta1.PoolRecord) + - [ShareRecord](#kava.swap.v1beta1.ShareRecord) + +- [kava/swap/v1beta1/genesis.proto](#kava/swap/v1beta1/genesis.proto) + - [GenesisState](#kava.swap.v1beta1.GenesisState) + +- [kava/swap/v1beta1/query.proto](#kava/swap/v1beta1/query.proto) + - [DepositResponse](#kava.swap.v1beta1.DepositResponse) + - [PoolResponse](#kava.swap.v1beta1.PoolResponse) + - [QueryDepositsRequest](#kava.swap.v1beta1.QueryDepositsRequest) + - [QueryDepositsResponse](#kava.swap.v1beta1.QueryDepositsResponse) + - [QueryParamsRequest](#kava.swap.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#kava.swap.v1beta1.QueryParamsResponse) + - [QueryPoolsRequest](#kava.swap.v1beta1.QueryPoolsRequest) + - [QueryPoolsResponse](#kava.swap.v1beta1.QueryPoolsResponse) + + - [Query](#kava.swap.v1beta1.Query) + +- [kava/swap/v1beta1/tx.proto](#kava/swap/v1beta1/tx.proto) + - [MsgDeposit](#kava.swap.v1beta1.MsgDeposit) + - [MsgDepositResponse](#kava.swap.v1beta1.MsgDepositResponse) + - [MsgSwapExactForTokens](#kava.swap.v1beta1.MsgSwapExactForTokens) + - [MsgSwapExactForTokensResponse](#kava.swap.v1beta1.MsgSwapExactForTokensResponse) + - [MsgSwapForExactTokens](#kava.swap.v1beta1.MsgSwapForExactTokens) + - [MsgSwapForExactTokensResponse](#kava.swap.v1beta1.MsgSwapForExactTokensResponse) + - [MsgWithdraw](#kava.swap.v1beta1.MsgWithdraw) + - [MsgWithdrawResponse](#kava.swap.v1beta1.MsgWithdrawResponse) + + - [Msg](#kava.swap.v1beta1.Msg) - [kava/validatorvesting/v1beta1/query.proto](#kava/validatorvesting/v1beta1/query.proto) - [QueryCirculatingSupplyHARDRequest](#kava.validatorvesting.v1beta1.QueryCirculatingSupplyHARDRequest) @@ -3656,7 +3995,615 @@ Msg defines the issuance Msg service. - + + +### CoreReward +CoreReward defines the reward weights for core infrastructure providers. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `address` | [bytes](#bytes) | | | +| `weight` | [string](#string) | | | + + + + + + + + +### InfrastructureParams +InfrastructureParams define the parameters for infrastructure rewards. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `infrastructure_periods` | [Period](#kava.kavadist.v1beta1.Period) | repeated | | +| `core_rewards` | [CoreReward](#kava.kavadist.v1beta1.CoreReward) | repeated | | +| `partner_rewards` | [PartnerReward](#kava.kavadist.v1beta1.PartnerReward) | repeated | | + + + + + + + + +### Params +Params governance parameters for kavadist module + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `active` | [bool](#bool) | | | +| `periods` | [Period](#kava.kavadist.v1beta1.Period) | repeated | | +| `infrastructure_params` | [InfrastructureParams](#kava.kavadist.v1beta1.InfrastructureParams) | | | + + + + + + + + +### PartnerReward +PartnerRewards defines the reward schedule for partner infrastructure providers. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `address` | [bytes](#bytes) | | | +| `rewards_per_second` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | + + + + + + + + +### Period +Period stores the specified start and end dates, and the inflation, expressed as a decimal +representing the yearly APR of KAVA tokens that will be minted during that period + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `start` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | example "2020-03-01T15:20:00Z" | +| `end` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | example "2020-06-01T15:20:00Z" | +| `inflation` | [bytes](#bytes) | | example "1.000000003022265980" - 10% inflation | + + + + + + + + + + + + + + + + +

Top

+ +## kava/kavadist/v1beta1/genesis.proto + + + + + +### GenesisState +GenesisState defines the kavadist module's genesis state. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `params` | [Params](#kava.kavadist.v1beta1.Params) | | | +| `previous_block_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | + + + + + + + + + + + + + + + + +

Top

+ +## kava/kavadist/v1beta1/proposal.proto + + + + + +### CommunityPoolMultiSpendProposal +CommunityPoolMultiSpendProposal spends from the community pool by sending to one or more +addresses + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | +| `recipient_list` | [MultiSpendRecipient](#kava.kavadist.v1beta1.MultiSpendRecipient) | repeated | | + + + + + + + + +### CommunityPoolMultiSpendProposalJSON +CommunityPoolMultiSpendProposalJSON defines a CommunityPoolMultiSpendProposal with a deposit + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | +| `recipient_list` | [MultiSpendRecipient](#kava.kavadist.v1beta1.MultiSpendRecipient) | repeated | | +| `deposit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | + + + + + + + + +### MultiSpendRecipient +MultiSpendRecipient defines a recipient and the amount of coins they are receiving + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `address` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | + + + + + + + + + + + + + + + + +

Top

+ +## kava/kavadist/v1beta1/query.proto + + + + + +### QueryBalanceRequest +QueryBalanceRequest defines the request type for querying x/kavadist balance. + + + + + + + + +### QueryBalanceResponse +QueryBalanceResponse defines the response type for querying x/kavadist balance. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | + + + + + + + + +### QueryParamsRequest +QueryParamsRequest defines the request type for querying x/kavadist parameters. + + + + + + + + +### QueryParamsResponse +QueryParamsResponse defines the response type for querying x/kavadist parameters. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `params` | [Params](#kava.kavadist.v1beta1.Params) | | | + + + + + + + + + + + + + + +### Query +Query defines the gRPC querier service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Params` | [QueryParamsRequest](#kava.kavadist.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#kava.kavadist.v1beta1.QueryParamsResponse) | Params queries the parameters of x/kavadist module. | GET|/kava/kavadist/v1beta1/parameters| +| `Balance` | [QueryBalanceRequest](#kava.kavadist.v1beta1.QueryBalanceRequest) | [QueryBalanceResponse](#kava.kavadist.v1beta1.QueryBalanceResponse) | Balance queries the balance of all coins of x/kavadist module. | GET|/kava/kavadist/v1beta1/balance| + + + + + + +

Top

+ +## kava/liquid/v1beta1/query.proto + + + + + +### QueryDelegatedBalanceRequest +QueryDelegatedBalanceRequest defines the request type for Query/DelegatedBalance method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `delegator` | [string](#string) | | delegator is the address of the account to query | + + + + + + + + +### QueryDelegatedBalanceResponse +DelegatedBalanceResponse defines the response type for the Query/DelegatedBalance method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `vested` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | vested is the amount of all delegated coins that have vested (ie not locked) | +| `vesting` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | vesting is the amount of all delegated coins that are still vesting (ie locked) | + + + + + + + + +### QueryTotalSupplyRequest +QueryTotalSupplyRequest defines the request type for Query/TotalSupply method. + + + + + + + + +### QueryTotalSupplyResponse +TotalSupplyResponse defines the response type for the Query/TotalSupply method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `height` | [int64](#int64) | | Height is the block height at which these totals apply | +| `result` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | Result is a list of coins supplied to liquid | + + + + + + + + + + + + + + +### Query +Query defines the gRPC querier service for liquid module + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `DelegatedBalance` | [QueryDelegatedBalanceRequest](#kava.liquid.v1beta1.QueryDelegatedBalanceRequest) | [QueryDelegatedBalanceResponse](#kava.liquid.v1beta1.QueryDelegatedBalanceResponse) | DelegatedBalance returns an account's vesting and vested coins currently delegated to validators. It ignores coins in unbonding delegations. | GET|/kava/liquid/v1beta1/delegated_balance/{delegator}| +| `TotalSupply` | [QueryTotalSupplyRequest](#kava.liquid.v1beta1.QueryTotalSupplyRequest) | [QueryTotalSupplyResponse](#kava.liquid.v1beta1.QueryTotalSupplyResponse) | TotalSupply returns the total sum of all coins currently locked into the liquid module. | GET|/kava/liquid/v1beta1/total_supply| + + + + + + +

Top

+ +## kava/liquid/v1beta1/tx.proto + + + + + +### MsgBurnDerivative +MsgBurnDerivative defines the Msg/BurnDerivative request type. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `sender` | [string](#string) | | sender is the owner of the derivatives to be converted | +| `validator` | [string](#string) | | validator is the validator of the derivatives to be converted | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | amount is the quantity of derivatives to be converted | + + + + + + + + +### MsgBurnDerivativeResponse +MsgBurnDerivativeResponse defines the Msg/BurnDerivative response type. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `received` | [string](#string) | | received is the number of delegation shares sent to the sender | + + + + + + + + +### MsgMintDerivative +MsgMintDerivative defines the Msg/MintDerivative request type. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `sender` | [string](#string) | | sender is the owner of the delegation to be converted | +| `validator` | [string](#string) | | validator is the validator of the delegation to be converted | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | amount is the quantity of staked assets to be converted | + + + + + + + + +### MsgMintDerivativeResponse +MsgMintDerivativeResponse defines the Msg/MintDerivative response type. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `received` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | received is the amount of staking derivative minted and sent to the sender | + + + + + + + + + + + + + + +### Msg +Msg defines the liquid Msg service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `MintDerivative` | [MsgMintDerivative](#kava.liquid.v1beta1.MsgMintDerivative) | [MsgMintDerivativeResponse](#kava.liquid.v1beta1.MsgMintDerivativeResponse) | MintDerivative defines a method for converting a delegation into staking deriviatives. | | +| `BurnDerivative` | [MsgBurnDerivative](#kava.liquid.v1beta1.MsgBurnDerivative) | [MsgBurnDerivativeResponse](#kava.liquid.v1beta1.MsgBurnDerivativeResponse) | BurnDerivative defines a method for converting staking deriviatives into a delegation. | | + + + + + + +

Top

+ +## kava/precisebank/v1/genesis.proto + + + + + +### FractionalBalance +FractionalBalance defines the fractional portion of an account balance + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `address` | [string](#string) | | address is the address of the balance holder. | +| `amount` | [string](#string) | | amount indicates amount of only the fractional balance owned by the address. FractionalBalance currently only supports tracking 1 single asset, e.g. fractional balances of ukava. | + + + + + + + + +### GenesisState +GenesisState defines the precisebank module's genesis state. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `balances` | [FractionalBalance](#kava.precisebank.v1.FractionalBalance) | repeated | balances is a list of all the balances in the precisebank module. | +| `remainder` | [string](#string) | | remainder is an internal value of how much extra fractional digits are still backed by the reserve, but not assigned to any account. | + + + + + + + + + + + + + + + + +

Top

+ +## kava/precisebank/v1/query.proto + + + + + +### QueryFractionalBalanceRequest +QueryFractionalBalanceRequest defines the request type for Query/FractionalBalance method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `address` | [string](#string) | | address is the account address to query fractional balance for. | + + + + + + + + +### QueryFractionalBalanceResponse +QueryFractionalBalanceResponse defines the response type for Query/FractionalBalance method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `fractional_balance` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | fractional_balance is the fractional balance of the address. | + + + + + + + + +### QueryRemainderRequest +QueryRemainderRequest defines the request type for Query/Remainder method. + + + + + + + + +### QueryRemainderResponse +QueryRemainderResponse defines the response type for Query/Remainder method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `remainder` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | remainder is the amount backed by the reserve, but not yet owned by any account, i.e. not in circulation. | + + + + + + + + +### QueryTotalFractionalBalancesRequest +QueryTotalFractionalBalancesRequest defines the request type for Query/TotalFractionalBalances method. + + + + + + + + +### QueryTotalFractionalBalancesResponse +QueryTotalFractionalBalancesResponse defines the response type for Query/TotalFractionalBalances method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `total` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | total is the total sum of all fractional balances managed by the precisebank module. | + + + + + + + + + + + + + + +### Query +Query defines the gRPC querier service for precisebank module + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `TotalFractionalBalances` | [QueryTotalFractionalBalancesRequest](#kava.precisebank.v1.QueryTotalFractionalBalancesRequest) | [QueryTotalFractionalBalancesResponse](#kava.precisebank.v1.QueryTotalFractionalBalancesResponse) | TotalFractionalBalances returns the total sum of all fractional balances managed by the precisebank module. | GET|/kava/precisebank/v1/total_fractional_balances| +| `Remainder` | [QueryRemainderRequest](#kava.precisebank.v1.QueryRemainderRequest) | [QueryRemainderResponse](#kava.precisebank.v1.QueryRemainderResponse) | Remainder returns the amount backed by the reserve, but not yet owned by any account, i.e. not in circulation. | GET|/kava/precisebank/v1/remainder| +| `FractionalBalance` | [QueryFractionalBalanceRequest](#kava.precisebank.v1.QueryFractionalBalanceRequest) | [QueryFractionalBalanceResponse](#kava.precisebank.v1.QueryFractionalBalanceResponse) | FractionalBalance returns only the fractional balance of an address. This does not include any integer balance. | GET|/kava/precisebank/v1/fractional_balance/{address}| + + + + + + +

Top

+ +## kava/pricefeed/v1beta1/store.proto + + + + ### CurrentPrice CurrentPrice defines a current price for a particular market in the pricefeed diff --git a/go.mod b/go.mod index ecf7edc7..98c401c6 100644 --- a/go.mod +++ b/go.mod @@ -4,61 +4,62 @@ go 1.21 require ( cosmossdk.io/errors v1.0.1 + cosmossdk.io/log v1.3.1 cosmossdk.io/math v1.3.0 cosmossdk.io/simapp v0.0.0-20231127212628-044ff4d8c015 + github.com/Kava-Labs/opendb v0.0.0-20240719173129-a2f11f6d7e51 github.com/cenkalti/backoff/v4 v4.1.3 - github.com/cometbft/cometbft v0.37.4 + github.com/cometbft/cometbft v0.37.9 github.com/cometbft/cometbft-db v0.9.1 github.com/coniks-sys/coniks-go v0.0.0-20180722014011-11acf4819b71 github.com/consensys/gnark-crypto v0.12.1 - github.com/cosmos/cosmos-proto v1.0.0-beta.4 + github.com/cosmos/cosmos-db v1.0.2 + github.com/cosmos/cosmos-proto v1.0.0-beta.5 github.com/cosmos/cosmos-sdk v0.47.10 github.com/cosmos/go-bip39 v1.0.0 github.com/cosmos/gogoproto v1.4.10 - github.com/cosmos/iavl v0.20.1 + github.com/cosmos/iavl v1.2.0 github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7 v7.1.3 github.com/cosmos/ibc-go/modules/light-clients/08-wasm v0.1.1-ibc-go-v7.3-wasmvm-v1.5 github.com/cosmos/ibc-go/v7 v7.4.0 github.com/ethereum/go-ethereum v1.10.26 github.com/evmos/ethermint v0.21.0 - github.com/go-kit/kit v0.12.0 github.com/gogo/protobuf v1.3.2 - github.com/golang/protobuf v1.5.3 + github.com/golang/protobuf v1.5.4 github.com/gorilla/mux v1.8.0 github.com/grpc-ecosystem/grpc-gateway v1.16.0 - github.com/linxGnu/grocksdb v1.8.6 + github.com/linxGnu/grocksdb v1.8.13 github.com/pelletier/go-toml/v2 v2.1.0 - github.com/prometheus/client_golang v1.14.0 github.com/shopspring/decimal v1.4.0 github.com/spf13/cast v1.6.0 - github.com/spf13/cobra v1.7.0 - github.com/spf13/viper v1.16.0 - github.com/stretchr/testify v1.8.4 + github.com/spf13/cobra v1.8.0 + github.com/spf13/viper v1.18.2 + github.com/stretchr/testify v1.9.0 github.com/subosito/gotenv v1.6.0 golang.org/x/crypto v0.24.0 golang.org/x/exp v0.0.0-20230905200255-921286631fa9 - google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0 - google.golang.org/grpc v1.60.1 - google.golang.org/protobuf v1.32.0 + google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de + google.golang.org/grpc v1.63.2 + google.golang.org/protobuf v1.33.0 sigs.k8s.io/yaml v1.4.0 ) require ( - cloud.google.com/go v0.111.0 // indirect - cloud.google.com/go/compute v1.23.3 // indirect + cloud.google.com/go v0.112.0 // indirect + cloud.google.com/go/compute v1.24.0 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v1.1.5 // indirect - cloud.google.com/go/storage v1.35.1 // indirect + cloud.google.com/go/iam v1.1.6 // indirect + cloud.google.com/go/storage v1.36.0 // indirect cosmossdk.io/api v0.3.1 // indirect cosmossdk.io/core v0.6.1 // indirect cosmossdk.io/depinject v1.0.0-alpha.4 // indirect - cosmossdk.io/log v1.3.1 // indirect cosmossdk.io/tools/rosetta v0.2.1 // indirect filippo.io/edwards25519 v1.0.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.1 // indirect github.com/ChainSafe/go-schnorrkel v1.0.0 // indirect github.com/CosmWasm/wasmvm v1.5.2 // indirect + github.com/DataDog/zstd v1.5.5 // indirect github.com/StackExchange/wmi v1.2.1 // indirect github.com/VictoriaMetrics/fastcache v1.6.0 // indirect github.com/armon/go-metrics v0.4.1 // indirect @@ -67,30 +68,32 @@ require ( github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect github.com/bits-and-blooms/bitset v1.7.0 // indirect - github.com/btcsuite/btcd v0.23.4 // indirect + github.com/btcsuite/btcd v0.24.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect - github.com/btcsuite/btcd/btcutil v1.1.3 // indirect - github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect + github.com/btcsuite/btcd/btcutil v1.1.5 // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect github.com/cespare/xxhash v1.1.0 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/chzyer/readline v1.5.1 // indirect github.com/cockroachdb/apd/v2 v2.0.2 // indirect - github.com/cockroachdb/errors v1.10.0 // indirect + github.com/cockroachdb/errors v1.11.1 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect + github.com/cockroachdb/pebble v1.1.0 // indirect github.com/cockroachdb/redact v1.1.5 // indirect + github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect github.com/coinbase/rosetta-sdk-go v0.7.9 // indirect github.com/confio/ics23/go v0.9.0 // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/cosmos/btcutil v1.0.5 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/ics23/go v0.10.0 // indirect - github.com/cosmos/ledger-cosmos-go v0.13.1 // indirect + github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect github.com/cosmos/rosetta-sdk-go v0.10.0 // indirect github.com/creachadair/taskgroup v0.4.2 // indirect github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/deckarep/golang-set v1.8.0 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect github.com/dgraph-io/badger/v2 v2.2007.4 // indirect github.com/dgraph-io/ristretto v0.1.1 // indirect @@ -100,20 +103,22 @@ require ( github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.6.0 // indirect github.com/edsrzf/mmap-go v1.0.0 // indirect - github.com/felixge/httpsnoop v1.0.2 // indirect + github.com/emicklei/dot v1.6.1 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect - github.com/getsentry/sentry-go v0.23.0 // indirect + github.com/getsentry/sentry-go v0.27.0 // indirect + github.com/go-kit/kit v0.13.0 // indirect github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.6.0 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect github.com/go-stack/stack v1.8.1 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/googleapis v1.4.1 // indirect - github.com/golang/glog v1.1.2 // indirect + github.com/golang/glog v1.2.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/mock v1.6.0 // indirect github.com/golang/snappy v0.0.4 // indirect @@ -121,7 +126,7 @@ require ( github.com/google/go-cmp v0.6.0 // indirect github.com/google/orderedcode v0.0.1 // indirect github.com/google/s2a-go v0.1.7 // indirect - github.com/google/uuid v1.4.0 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect github.com/googleapis/gax-go/v2 v2.12.0 // indirect github.com/gorilla/handlers v1.5.1 // indirect @@ -131,11 +136,12 @@ require ( github.com/gtank/merlin v0.1.1 // indirect github.com/gtank/ristretto255 v0.1.2 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-getter v1.7.1 // indirect + github.com/hashicorp/go-getter v1.7.5 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-safetemp v1.0.0 // indirect github.com/hashicorp/go-version v1.6.0 // indirect - github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect + github.com/hashicorp/golang-lru v1.0.2 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hdevalence/ed25519consensus v0.1.0 // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect @@ -148,11 +154,10 @@ require ( github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect - github.com/klauspost/compress v1.17.0 // indirect + github.com/klauspost/compress v1.17.7 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/lib/pq v1.10.7 // indirect - github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/manifoldco/promptui v0.9.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect @@ -167,28 +172,33 @@ require ( github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/mtibben/percent v0.2.1 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect + github.com/patrickmn/go-cache v2.1.0+incompatible // indirect + github.com/petermattis/goid v0.0.0-20231207134359-e60b3f734c67 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_model v0.3.0 // indirect + github.com/prometheus/client_golang v1.14.0 // indirect + github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.42.0 // indirect - github.com/prometheus/procfs v0.9.0 // indirect + github.com/prometheus/procfs v0.13.0 // indirect github.com/prometheus/tsdb v0.7.1 // indirect github.com/rakyll/statik v0.1.7 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rjeczalik/notify v0.9.1 // indirect - github.com/rogpeppe/go-internal v1.11.0 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/rs/cors v1.8.3 // indirect github.com/rs/zerolog v1.32.0 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sasha-s/go-deadlock v0.3.1 // indirect github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect + github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect - github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/status-im/keycard-go v0.2.0 // indirect + github.com/stretchr/objx v0.5.2 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tendermint/go-amino v0.16.0 // indirect - github.com/tidwall/btree v1.6.0 // indirect + github.com/tidwall/btree v1.7.0 // indirect github.com/tklauser/go-sysconf v0.3.10 // indirect github.com/tklauser/numcpus v0.4.0 // indirect github.com/tyler-smith/go-bip39 v1.1.0 // indirect @@ -197,20 +207,24 @@ require ( github.com/zondax/ledger-go v0.14.3 // indirect go.etcd.io/bbolt v1.3.8 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/otel v1.19.0 // indirect - go.opentelemetry.io/otel/metric v1.19.0 // indirect - go.opentelemetry.io/otel/trace v1.19.0 // indirect - golang.org/x/net v0.21.0 // indirect - golang.org/x/oauth2 v0.15.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 // indirect + go.opentelemetry.io/otel v1.22.0 // indirect + go.opentelemetry.io/otel/metric v1.22.0 // indirect + go.opentelemetry.io/otel/trace v1.22.0 // indirect + go.uber.org/atomic v1.10.0 // indirect + go.uber.org/multierr v1.9.0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/oauth2 v0.17.0 // indirect golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.21.0 // indirect golang.org/x/term v0.21.0 // indirect golang.org/x/text v0.16.0 // indirect golang.org/x/time v0.5.0 // indirect - google.golang.org/api v0.153.0 // indirect + google.golang.org/api v0.162.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1 // indirect + google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect @@ -224,20 +238,23 @@ replace ( // Use the cosmos keyring code github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 // Use cometbft fork of tendermint - github.com/cometbft/cometbft => github.com/kava-labs/cometbft v0.37.4-kava.1 - github.com/cometbft/cometbft-db => github.com/kava-labs/cometbft-db v0.9.1-kava.1 + github.com/cometbft/cometbft => github.com/0glabs/cometbft v0.37.9-0glabs.1 + github.com/cometbft/cometbft-db => github.com/kava-labs/cometbft-db v0.9.1-kava.2 // Use cosmos-sdk fork with backported fix for unsafe-reset-all, staking transfer events, and custom tally handler support // github.com/cosmos/cosmos-sdk => github.com/0glabs/cosmos-sdk v0.46.11-kava.3 - github.com/cosmos/cosmos-sdk => github.com/0glabs/cosmos-sdk v0.47.10-0glabs.3 + github.com/cosmos/cosmos-sdk => github.com/0glabs/cosmos-sdk v0.47.10-0glabs.7 + github.com/cosmos/iavl => github.com/kava-labs/iavl v1.2.0-kava.1 // See https://github.com/cosmos/cosmos-sdk/pull/13093 github.com/dgrijalva/jwt-go => github.com/golang-jwt/jwt/v4 v4.4.2 - // Use go-ethereum fork with precompiles + // Tracking kava-labs/go-ethereum kava/release/v1.10 branch + // TODO: Tag before release github.com/ethereum/go-ethereum => github.com/evmos/go-ethereum v1.10.26-evmos-rc2 // Use ethermint fork that respects min-gas-price with NoBaseFee true and london enabled, and includes eip712 support - github.com/evmos/ethermint => github.com/0glabs/ethermint v0.21.0-0g.v3.0.3 + github.com/evmos/ethermint => github.com/0glabs/ethermint v0.21.0-0g.v3.1.7 // See https://github.com/cosmos/cosmos-sdk/pull/10401, https://github.com/cosmos/cosmos-sdk/commit/0592ba6158cd0bf49d894be1cef4faeec59e8320 github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.9.0 // Downgraded to avoid bugs in following commits which causes "version does not exist" errors github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 + // Avoid change in slices.SortFunc, see https://github.com/cosmos/cosmos-sdk/issues/20159 golang.org/x/exp => golang.org/x/exp v0.0.0-20230711153332-06a737ee72cb ) diff --git a/go.sum b/go.sum index 2120af9b..796986e6 100644 --- a/go.sum +++ b/go.sum @@ -32,8 +32,8 @@ cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w9 cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= -cloud.google.com/go v0.111.0 h1:YHLKNupSD1KqjDbQ3+LVdQ81h/UJbJyZG203cEfnQgM= -cloud.google.com/go v0.111.0/go.mod h1:0mibmpKP1TyOOFYQY5izo0LnT+ecvOQ0Sg3OdmMiNRU= +cloud.google.com/go v0.112.0 h1:tpFCD7hpHFlQ8yPwT3x+QeXqc2T6+n6T+hmABHfDUSM= +cloud.google.com/go v0.112.0/go.mod h1:3jEEVwZ/MHU4djK5t5RHuKOA/GbLddgTdVubX1qnPD4= cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= @@ -71,8 +71,8 @@ cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= -cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= -cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= +cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg= +cloud.google.com/go/compute v1.24.0/go.mod h1:kw1/T+h/+tK2LJK0wiPPx1intgdAM3j/g3hFDlscY40= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= @@ -112,8 +112,8 @@ cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y97 cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= -cloud.google.com/go/iam v1.1.5 h1:1jTsCu4bcsNsE4iiqNT5SHwrDRCfRmIaaaVFhRveTJI= -cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8= +cloud.google.com/go/iam v1.1.6 h1:bEa06k05IO4f4uJonbB5iAgKTPpABy1ayxaIZV/GHVc= +cloud.google.com/go/iam v1.1.6/go.mod h1:O0zxdPeGBoFdWW3HWmBxJsk0pfvNM/p/qa82rWOGTwI= cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= @@ -174,8 +174,8 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= -cloud.google.com/go/storage v1.35.1 h1:B59ahL//eDfx2IIKFBeT5Atm9wnNmj3+8xG/W4WB//w= -cloud.google.com/go/storage v1.35.1/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8= +cloud.google.com/go/storage v1.36.0 h1:P0mOkAcaJxhCTvAkMhxMfrTKiNcub4YmmPBtlhAyTr8= +cloud.google.com/go/storage v1.36.0/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8= cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= @@ -209,10 +209,12 @@ filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek= filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= git.sr.ht/~sircmpwn/getopt v0.0.0-20191230200459-23622cc906b3/go.mod h1:wMEGFFFNuPos7vHmWXfszqImLppbc0wEhh6JBfJIUgw= git.sr.ht/~sircmpwn/go-bare v0.0.0-20210406120253-ab86bc2846d9/go.mod h1:BVJwbDfVjCjoFiKrhkei6NdGcZYpkDkdyCdg1ukytRA= -github.com/0glabs/cosmos-sdk v0.47.10-0glabs.3 h1:Wx3tVMTuFaaHDeJT/OzT7QLfAIpeaZsG9R6XoTOyKCw= -github.com/0glabs/cosmos-sdk v0.47.10-0glabs.3/go.mod h1:BWo24B8cApWcO2/widWYIdt3CPxbh+HCSypCPpjTjog= -github.com/0glabs/ethermint v0.21.0-0g.v3.0.3 h1:QNrXBQV5L/9FvYRUzJRXMV745xBmJhIP0aEdo0u8x+8= -github.com/0glabs/ethermint v0.21.0-0g.v3.0.3/go.mod h1:HYQUhvcZBIG71H3xlxQSk0XyQEjeaHsduOj6O2QImrE= +github.com/0glabs/cometbft v0.37.9-0glabs.1 h1:KQJG17Y21suKP3QNICLto4b5Ak73XbSmKxeLbg0ZM68= +github.com/0glabs/cometbft v0.37.9-0glabs.1/go.mod h1:j0Q3RqrCd+cztWCugs3obbzC4NyHGBPZZjtm/fWV00I= +github.com/0glabs/cosmos-sdk v0.47.10-0glabs.7 h1:6+JquK9BaZZdIA3gx1AXhPBAdYCG+FQ94Y7FN35CvB4= +github.com/0glabs/cosmos-sdk v0.47.10-0glabs.7/go.mod h1:KskIVnhXTFqrw7CDccMvx7To5KzUsOomIsQV7sPGOog= +github.com/0glabs/ethermint v0.21.0-0g.v3.1.7 h1:wzr6z/LTsbjoAaBf0JkMtIDl/+B5KLd0GrU5brSZCY0= +github.com/0glabs/ethermint v0.21.0-0g.v3.1.7/go.mod h1:S1Ahmqpzo1XUsfmmpGT7ok0hu5Fekz/pD6EDtXaBg9Q= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1/go.mod h1:fBF9PQNqB8scdgpZ3ufzaLntG0AG7C1WjPMsiFOmfHM= @@ -229,9 +231,13 @@ github.com/CosmWasm/wasmvm v1.5.2/go.mod h1:Q0bSEtlktzh7W2hhEaifrFp1Erx11ckQZmjq github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.5.0/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= +github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +github.com/Kava-Labs/opendb v0.0.0-20240719173129-a2f11f6d7e51 h1:tMTENCeSPIJO8yCpEQbT15XYXt4EFNQUx3s334uxVts= +github.com/Kava-Labs/opendb v0.0.0-20240719173129-a2f11f6d7e51/go.mod h1:LbPsJiWvj90NT3Y9YV8EFPkWfvp8A15Tp88qqKa3LxA= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= -github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= @@ -303,9 +309,9 @@ github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13P github.com/btcsuite/btcd v0.21.0-beta.0.20201114000516-e9c7a5ac6401/go.mod h1:Sv4JPQ3/M+teHz9Bo5jBpkNcP0x6r7rdihlNL/7tTAs= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y= -github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= -github.com/btcsuite/btcd v0.23.4 h1:IzV6qqkfwbItOS/sg/aDfPDsjPP8twrCOE2R93hxMlQ= -github.com/btcsuite/btcd v0.23.4/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= +github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= +github.com/btcsuite/btcd v0.24.0 h1:gL3uHE/IaFj6fcZSu03SvqPMSx7s/dPzfpG/atRwWdo= +github.com/btcsuite/btcd v0.24.0/go.mod h1:K4IDc1593s8jKXIF7yS7yCTSxrknB9z0STzc2j6XgE4= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= @@ -313,11 +319,12 @@ github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= -github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= -github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= +github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= +github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= @@ -349,8 +356,8 @@ github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s= github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= @@ -378,15 +385,23 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= github.com/cockroachdb/apd/v2 v2.0.2 h1:weh8u7Cneje73dDh+2tEVLUvyBc89iwepWCD8b8034E= github.com/cockroachdb/apd/v2 v2.0.2/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/cockroachdb/errors v1.10.0 h1:lfxS8zZz1+OjtV4MtNWgboi/W5tyLEB6VQZBXN+0VUU= -github.com/cockroachdb/errors v1.10.0/go.mod h1:lknhIsEVQ9Ss/qKDBQS/UqFSvPQjOwNq2qyKAxtHRqE= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= +github.com/cockroachdb/errors v1.11.1 h1:xSEW75zKaKCWzR3OfxXUxgrk/NtT4G1MiOv5lWZazG8= +github.com/cockroachdb/errors v1.11.1/go.mod h1:8MUxA3Gi6b25tYlFEBGLf+D8aISL+M4MIpiWMSNRfxw= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/pebble v1.1.0 h1:pcFh8CdCIt2kmEpK0OIatq67Ln9uGDYY3d5XnE0LJG4= +github.com/cockroachdb/pebble v1.1.0/go.mod h1:sEHm5NOXxyiAoKWhoFxT8xMgd/f3RA6qUqQ1BXKrh2E= github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/coinbase/kryptology v1.8.0/go.mod h1:RYXOAPdzOGUe3qlSFkMGn58i3xUA8hmxYHksuq+8ciI= github.com/coinbase/rosetta-sdk-go v0.7.9 h1:lqllBjMnazTjIqYrOGv8h8jxjg9+hJazIGZr9ZvoCcA= @@ -413,8 +428,10 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-proto v1.0.0-beta.4 h1:aEL7tU/rLOmxZQ9z4i7mzxcLbSCY48OdY7lIWTLG7oU= -github.com/cosmos/cosmos-proto v1.0.0-beta.4/go.mod h1:oeB+FyVzG3XrQJbJng0EnV8Vljfk9XvTIpGILNU/9Co= +github.com/cosmos/cosmos-db v1.0.2 h1:hwMjozuY1OlJs/uh6vddqnk9j7VamLv+0DBlbEXbAKs= +github.com/cosmos/cosmos-db v1.0.2/go.mod h1:Z8IXcFJ9PqKK6BIsVOB3QXtkKoqUOp1vRvPT39kOXEA= +github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= +github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= @@ -423,8 +440,6 @@ github.com/cosmos/gogogateway v1.2.0/go.mod h1:iQpLkGWxYcnCdz5iAdLcRBSw3h7NXeOkZ github.com/cosmos/gogoproto v1.4.2/go.mod h1:cLxOsn1ljAHSV527CHOtaIP91kK6cCrZETRBrkzItWU= github.com/cosmos/gogoproto v1.4.10 h1:QH/yT8X+c0F4ZDacDv3z+xE3WU1P1Z3wQoLMBRJoKuI= github.com/cosmos/gogoproto v1.4.10/go.mod h1:3aAZzeRWpAwr+SS/LLkICX2/kDFyaYVzckBDzygIxek= -github.com/cosmos/iavl v0.20.1 h1:rM1kqeG3/HBT85vsZdoSNsehciqUQPWrR4BYmqE2+zg= -github.com/cosmos/iavl v0.20.1/go.mod h1:WO7FyvaZJoH65+HFOsDir7xU9FWk2w9cHXNW1XHcl7A= github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7 v7.1.3 h1:MZGDMETv72suFpTAD6VPGqSIm1FJcChtk2HmVh9D+Bo= github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7 v7.1.3/go.mod h1:UvDmcGIWJPIytq+Q78/ff5NTOsuX/7IrNgEugTW5i0s= github.com/cosmos/ibc-go/modules/light-clients/08-wasm v0.1.1-ibc-go-v7.3-wasmvm-v1.5 h1:sMoHjep+KInjMrppNCEutMVm1p8nI9WhKCuMQ+EcUHw= @@ -435,15 +450,16 @@ github.com/cosmos/ics23/go v0.10.0 h1:iXqLLgp2Lp+EdpIuwXTYIQU+AiHj9mOC2X9ab++bZD github.com/cosmos/ics23/go v0.10.0/go.mod h1:ZfJSmng/TBNTBkFemHHHj5YY7VAU/MBU980F4VU1NG0= github.com/cosmos/keyring v1.2.0 h1:8C1lBP9xhImmIabyXW4c3vFjjLiBdGCmfLUfeZlV1Yo= github.com/cosmos/keyring v1.2.0/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= -github.com/cosmos/ledger-cosmos-go v0.13.1 h1:12ac9+GwBb9BjP7X5ygpFk09Itwzjzfmg6A2CWFjoVs= -github.com/cosmos/ledger-cosmos-go v0.13.1/go.mod h1:5tv2RVJEd2+Y38TIQN4CRjJeQGyqOEiKJDfqhk5UjqE= +github.com/cosmos/ledger-cosmos-go v0.13.3 h1:7ehuBGuyIytsXbd4MP43mLeoN2LTOEnk5nvue4rK+yM= +github.com/cosmos/ledger-cosmos-go v0.13.3/go.mod h1:HENcEP+VtahZFw38HZ3+LS3Iv5XV6svsnkk9vdJtLr8= github.com/cosmos/rosetta-sdk-go v0.10.0 h1:E5RhTruuoA7KTIXUcMicL76cffyeoyvNybzUGSKFTcM= github.com/cosmos/rosetta-sdk-go v0.10.0/go.mod h1:SImAZkb96YbwvoRkzSMQB6noNJXFgWl/ENIznEoYQI4= github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creachadair/taskgroup v0.4.2 h1:jsBLdAJE42asreGss2xZGZ8fJra7WtwnHWeJFxv2Li8= github.com/creachadair/taskgroup v0.4.2/go.mod h1:qiXUOSrbwAY3u0JPGTzObbE3yf9hcXHDKBZ2ZjpCbgM= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= @@ -459,11 +475,12 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4= github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= -github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M= github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw= @@ -504,6 +521,8 @@ github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFP github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/emicklei/dot v1.6.1 h1:ujpDlBkkwgWUY+qPId5IwapRW/xEoligRSYjioR6DFI= +github.com/emicklei/dot v1.6.1/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -515,13 +534,15 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= +github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= github.com/evmos/go-ethereum v1.10.26-evmos-rc2 h1:tYghk1ZZ8X4/OQ4YI9hvtm8aSN8OSqO0g9vo/sCMdBo= github.com/evmos/go-ethereum v1.10.26-evmos-rc2/go.mod h1:/6CsT5Ceen2WPLI/oCA3xMcZ5sWMF/D46SjM/ayY0Oo= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o= -github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= @@ -541,8 +562,8 @@ github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqG github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= -github.com/getsentry/sentry-go v0.23.0 h1:dn+QRCeJv4pPt9OjVXiMcGIBIefaTJPw/h0bZWO05nE= -github.com/getsentry/sentry-go v0.23.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= +github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= +github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= @@ -556,8 +577,8 @@ github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3Bop github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= -github.com/go-kit/kit v0.12.0 h1:e4o3o3IsBfAKQh5Qbbiqyfu97Ku7jrO/JbohvztANh4= -github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEaizzs= +github.com/go-kit/kit v0.13.0 h1:OoneCcHKHQ03LfBpoQCUfCluwd2Vt3ohz+kvbJneZAU= +github.com/go-kit/kit v0.13.0/go.mod h1:phqEHMMUbyrCFCTgH48JueqrM3md2HcAZ8N3XE4FKDg= github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= @@ -566,8 +587,8 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= @@ -620,8 +641,8 @@ github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= -github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= +github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= +github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -656,8 +677,8 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= @@ -723,8 +744,8 @@ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= -github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= @@ -780,8 +801,8 @@ github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-getter v1.7.1 h1:SWiSWN/42qdpR0MdhaOc/bLR48PLuP1ZQtYLRlM69uY= -github.com/hashicorp/go-getter v1.7.1/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= +github.com/hashicorp/go-getter v1.7.5 h1:dT58k9hQ/vbxNMwoI5+xFYAJuv6152UNvdHokfI5wE4= +github.com/hashicorp/go-getter v1.7.5/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -802,8 +823,11 @@ github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09 github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= @@ -880,10 +904,10 @@ github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8 github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F6iIOGgxJ5npU/IUOhOhqlVrGjyIZc8/MagT0= github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= -github.com/kava-labs/cometbft v0.37.4-kava.1 h1:QRuyBieWdUBpe4pcXgzu1SdMH2lkTaqXr/JPIeqdiHE= -github.com/kava-labs/cometbft v0.37.4-kava.1/go.mod h1:Cmg5Hp4sNpapm7j+x0xRyt2g0juQfmB752ous+pA0G8= -github.com/kava-labs/cometbft-db v0.9.1-kava.1 h1:0KmSPdXYdRp6TsgKuMxRnMZCMEGC5ysIVjuJddYr4tw= -github.com/kava-labs/cometbft-db v0.9.1-kava.1/go.mod h1:iliyWaoV0mRwBJoizElCwwRA9Tf7jZJOURcRZF9m60U= +github.com/kava-labs/cometbft-db v0.9.1-kava.2 h1:ZQaio886ifvml9XtJB4IYHhlArgA3+/a5Zwidg7H2J8= +github.com/kava-labs/cometbft-db v0.9.1-kava.2/go.mod h1:PvUZbx7zeR7I4CAvtKBoii/5ia5gXskKjDjIVpt7gDw= +github.com/kava-labs/iavl v1.2.0-kava.1 h1:HPme3nVrR25XshEFDckMg6fp0tVfpAjTi32/5Iiyuzk= +github.com/kava-labs/iavl v1.2.0-kava.1/go.mod h1:HidWWLVAtODJqFD6Hbne2Y0q3SdxByJepHUOeoH4LiI= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= @@ -894,8 +918,8 @@ github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= -github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= -github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5 h1:2U0HzY8BJ8hVwDKIzp7y4voR9CX/nvcfymLmg2UiOio= github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= @@ -925,12 +949,10 @@ github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ic github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= -github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= -github.com/linxGnu/grocksdb v1.8.6 h1:O7I6SIGPrypf3f/gmrrLUBQDKfO8uOoYdWf4gLS06tc= -github.com/linxGnu/grocksdb v1.8.6/go.mod h1:xZCIb5Muw+nhbDK4Y5UJuOrin5MceOuiXkVUR7vp4WY= +github.com/linxGnu/grocksdb v1.8.13 h1:X3Id7Obhf8qLY9WPc4LmmtIyabmdDf810XSFDnLlW7E= +github.com/linxGnu/grocksdb v1.8.13/go.mod h1:QYiYypR2d4v63Wj1adOOfzglnoII0gLj3PNh4fZkcFA= github.com/lucasjones/reggen v0.0.0-20180717132126-cdb49ff09d77/go.mod h1:5ELEyG+X8f+meRWHuqUOewBOhvHkl7M76pdGEansxW4= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -1067,6 +1089,8 @@ github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIw github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= +github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= @@ -1077,8 +1101,8 @@ github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9 github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= -github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 h1:hDSdbBuw3Lefr6R18ax0tZ2BJeNB3NehB3trOwYBsdU= -github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/petermattis/goid v0.0.0-20231207134359-e60b3f734c67 h1:jik8PHtAIsPlCRJjJzl4udgEf7hawInF9texMeO2jrU= +github.com/petermattis/goid v0.0.0-20231207134359-e60b3f734c67/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= @@ -1109,8 +1133,8 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1: github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= @@ -1127,8 +1151,8 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= -github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= +github.com/prometheus/procfs v0.13.0 h1:GqzLlQyfsPbaEHaQkO7tbDlriv/4o5Hudv6OXHGKX7o= +github.com/prometheus/procfs v0.13.0/go.mod h1:cd4PFCR54QLnGKPaKGA6l+cfuNXtht43ZKY6tow0Y1g= github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= @@ -1145,8 +1169,8 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.8.3 h1:O+qNyWn7Z+F9M0ILBHgMVPuB1xTOucVd5gtaYyXBpRo= github.com/rs/cors v1.8.3/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= @@ -1159,6 +1183,10 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= @@ -1182,6 +1210,8 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1 github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= @@ -1193,18 +1223,16 @@ github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc= -github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= @@ -1214,8 +1242,9 @@ github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5J github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -1227,8 +1256,9 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/supranational/blst v0.3.8-0.20220526154634-513d2456b344/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= @@ -1236,8 +1266,8 @@ github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= -github.com/tidwall/btree v1.6.0 h1:LDZfKfQIBHGHWSwckhXI0RPSXzlo+KYdjK7FWSqOzzg= -github.com/tidwall/btree v1.6.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= +github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI= +github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.14.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= @@ -1308,22 +1338,30 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= -go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= -go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE= -go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= -go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= -go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= -go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= -go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 h1:UNQQKPfTDe1J81ViolILjTKPr9WetKW6uei2hFgJmFs= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0/go.mod h1:r9vWsPS/3AQItv3OSlEJ/E4mbrhUbbw18meOjArPtKQ= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 h1:sv9kVfal0MK0wBMCOGr+HeJm9v803BkJxGrk2au7j08= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0/go.mod h1:SK2UL73Zy1quvRPonmOmRDiWk1KBV3LyIeeIxcEApWw= +go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y= +go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= +go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg= +go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= +go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= +go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= +go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0= +go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= +go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/mock v0.2.0 h1:TaP3xedm7JaAgScZO7tlvlKrqT0p7I6OsdGB5YNSMDU= go.uber.org/mock v0.2.0/go.mod h1:J0y0rp9L3xiff1+ZBfKxlC1fz2+aO16tw0tsDOixfuM= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= @@ -1452,8 +1490,8 @@ golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfS golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1479,8 +1517,8 @@ golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= -golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= -golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= +golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ= +golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1765,8 +1803,8 @@ google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= -google.golang.org/api v0.153.0 h1:N1AwGhielyKFaUqH07/ZSIQR3uNPcV7NVw0vj+j4iR4= -google.golang.org/api v0.153.0/go.mod h1:3qNJX5eOmhiWYc67jRA/3GsDw97UFb5ivv7Y2PrriAY= +google.golang.org/api v0.162.0 h1:Vhs54HkaEpkMBdgGdOT2P6F0csGG/vxDS0hWHJzmmps= +google.golang.org/api v0.162.0/go.mod h1:6SulDkfoBIg4NFmCuZ39XeeAgSHCPecfSUuDyYlAHs0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1885,12 +1923,12 @@ google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqw google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 h1:nz5NESFLZbJGPFxDT/HCn+V1mZ8JGNoY4nUpmW/Y2eg= -google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917/go.mod h1:pZqR+glSb11aJ+JQcczCvgf47+duRuzNSKqE8YAQnV0= -google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0 h1:s1w3X6gQxwrLEpxnLd/qXTVLgQE2yXwaOaoa6IlY/+o= -google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0/go.mod h1:CAny0tYF+0/9rmDB9fahA9YLzX3+AEVl1qXbv5hhj6c= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1 h1:gphdwh0npgs8elJ4T6J+DQJHPVF7RsuJHCfwztUb4J4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1/go.mod h1:daQN87bsDqDoe316QbbvX60nMoJQa4r6Ds0ZuoAe5yA= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= +google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0= +google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= @@ -1932,8 +1970,8 @@ google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= -google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -1950,8 +1988,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= -google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/golangci.yml b/golangci.yml deleted file mode 100644 index 371e83fa..00000000 --- a/golangci.yml +++ /dev/null @@ -1,52 +0,0 @@ -run: - tests: false -# # timeout for analysis, e.g. 30s, 5m, default is 1m -# timeout: 5m - -linters: - disable-all: true - enable: - - bodyclose - - deadcode - - depguard - - dogsled - # - errcheck - - goconst - - gocritic - - gofmt - - goimports - - golint - - gosec - - gosimple - - govet - - ineffassign - - interfacer - - maligned - - misspell - - nakedret - - prealloc - - scopelint - - staticcheck - - structcheck - - stylecheck - - typecheck - - unconvert - - unused - - misspell - - wsl - -issues: - exclude-rules: - - text: "Use of weak random number generator" - linters: - - gosec - - text: "comment on exported var" - linters: - - golint - -linters-settings: - dogsled: - max-blank-identifiers: 3 - maligned: - # print struct with more effective memory layout or not, false by default - suggest-new: true diff --git a/localtestnet.sh b/localtestnet.sh index 3dc39f04..3b6234a9 100755 --- a/localtestnet.sh +++ b/localtestnet.sh @@ -36,11 +36,14 @@ $BINARY init validator --chain-id $chainID sed -in-place='' 's/enable = false/enable = true/g' $DATA/config/app.toml # Set evm tracer to json -sed -in-place='' 's/tracer = ""/tracer = "json"/g' $DATA/config/app.toml +sed -in-place='' 's/tracer = ""/tracer = ""/g' $DATA/config/app.toml -# Enable full error trace to be returned on tx failure +# Disable full error trace sed -in-place='' '/iavl-cache-size/a\ -trace = true' $DATA/config/app.toml +trace = false' $DATA/config/app.toml + +# Set min gas prices +sed -in-place='' 's/minimum-gas-prices = "0ua0gi"/minimum-gas-prices = "0.01ua0gi,100000neuron"/g' $DATA/config/app.toml # Set client chain id sed -in-place='' 's/chain-id = ""/chain-id = "zgchain_8888-1"/g' $DATA/config/client.toml diff --git a/precompiles/common/errors.go b/precompiles/common/errors.go index ca8c494e..f7a93d8e 100644 --- a/precompiles/common/errors.go +++ b/precompiles/common/errors.go @@ -3,4 +3,5 @@ package common const ( ErrGetStateDB = "get EVM StateDB failed" ErrInvalidNumberOfArgs = "invalid number of arguments; expected %d; got: %d" + ErrSenderNotOrigin = "msg.sender is not from tx origin" ) diff --git a/precompiles/common/utils.go b/precompiles/common/utils.go new file mode 100644 index 00000000..a59544dc --- /dev/null +++ b/precompiles/common/utils.go @@ -0,0 +1,18 @@ +package common + +import ( + "math/big" + "strings" + + "cosmossdk.io/math" + "github.com/ethereum/go-ethereum/common" +) + +func ToLowerHexWithoutPrefix(addr common.Address) string { + return strings.ToLower(addr.Hex()[2:]) +} + +// BigIntToLegacyDec converts a uint number (18 decimals) to math.LegacyDec (18 decimals) +func BigIntToLegacyDec(x *big.Int) math.LegacyDec { + return math.LegacyNewDecFromBigIntWithPrec(x, math.LegacyPrecision) +} diff --git a/precompiles/dasigners/dasigners.go b/precompiles/dasigners/dasigners.go index 4e248753..c8cd7e15 100644 --- a/precompiles/dasigners/dasigners.go +++ b/precompiles/dasigners/dasigners.go @@ -139,11 +139,11 @@ func (d *DASignersPrecompile) Run(evm *vm.EVM, contract *vm.Contract, readonly b bz, err = d.RegisteredEpoch(ctx, evm, method, args) // txs case DASignersFunctionRegisterSigner: - bz, err = d.RegisterSigner(ctx, evm, stateDB, method, args) + bz, err = d.RegisterSigner(ctx, evm, stateDB, contract, method, args) case DASignersFunctionRegisterNextEpoch: - bz, err = d.RegisterNextEpoch(ctx, evm, stateDB, method, args) + bz, err = d.RegisterNextEpoch(ctx, evm, stateDB, contract, method, args) case DASignersFunctionUpdateSocket: - bz, err = d.UpdateSocket(ctx, evm, stateDB, method, args) + bz, err = d.UpdateSocket(ctx, evm, stateDB, contract, method, args) } if err != nil { diff --git a/precompiles/dasigners/dasigners_test.go b/precompiles/dasigners/dasigners_test.go index b36ef7d1..a1d356bc 100644 --- a/precompiles/dasigners/dasigners_test.go +++ b/precompiles/dasigners/dasigners_test.go @@ -14,6 +14,7 @@ import ( "github.com/0glabs/0g-chain/x/dasigners/v1/types" abci "github.com/cometbft/cometbft/abci/types" "github.com/consensys/gnark-crypto/ecc/bn254" + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" @@ -23,7 +24,6 @@ import ( "cosmossdk.io/math" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/ethereum/go-ethereum/core/vm" - "github.com/evmos/ethermint/crypto/ethsecp256k1" ) type DASignersTestSuite struct { @@ -44,8 +44,7 @@ func (suite *DASignersTestSuite) AddDelegation(from string, to string, amount ma suite.Require().NoError(err) validator, found := suite.StakingKeeper.GetValidator(suite.Ctx, valAddr) if !found { - consPriv, err := ethsecp256k1.GenerateKey() - suite.Require().NoError(err) + consPriv := ed25519.GenPrivKey() newValidator, err := stakingtypes.NewValidator(valAddr, consPriv.PubKey(), stakingtypes.Description{}) suite.Require().NoError(err) validator = newValidator @@ -73,8 +72,8 @@ func (suite *DASignersTestSuite) SetupTest() { suite.Assert().EqualValues(ok, true) suite.dasigners = precompile.(*dasignersprecompile.DASignersPrecompile) - suite.signerOne = testutil.GenSigner() - suite.signerTwo = testutil.GenSigner() + suite.signerOne = suite.GenSigner() + suite.signerTwo = suite.GenSigner() abi, err := abi.JSON(strings.NewReader(dasignersprecompile.DASignersABI)) suite.Assert().NoError(err) suite.abi = abi diff --git a/precompiles/dasigners/query.go b/precompiles/dasigners/query.go index 6f518761..82a595b7 100644 --- a/precompiles/dasigners/query.go +++ b/precompiles/dasigners/query.go @@ -62,7 +62,7 @@ func (d *DASignersPrecompile) IsSigner(ctx sdk.Context, _ *vm.EVM, method *abi.M if len(args) != 1 { return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 1, len(args)) } - account := ToLowerHexWithoutPrefix(args[0].(common.Address)) + account := precopmiles_common.ToLowerHexWithoutPrefix(args[0].(common.Address)) _, found, err := d.dasignersKeeper.GetSigner(ctx, account) if err != nil { return nil, err @@ -74,7 +74,7 @@ func (d *DASignersPrecompile) RegisteredEpoch(ctx sdk.Context, _ *vm.EVM, method if len(args) != 2 { return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args)) } - account := ToLowerHexWithoutPrefix(args[0].(common.Address)) + account := precopmiles_common.ToLowerHexWithoutPrefix(args[0].(common.Address)) epoch := args[1].(*big.Int).Uint64() _, found, err := d.dasignersKeeper.GetRegistration(ctx, epoch, account) if err != nil { diff --git a/precompiles/dasigners/tx.go b/precompiles/dasigners/tx.go index ac7a7a5c..c7663dfa 100644 --- a/precompiles/dasigners/tx.go +++ b/precompiles/dasigners/tx.go @@ -7,18 +7,30 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/core/vm" "github.com/evmos/ethermint/x/evm/statedb" + + precopmiles_common "github.com/0glabs/0g-chain/precompiles/common" ) -func (d *DASignersPrecompile) RegisterSigner(ctx sdk.Context, evm *vm.EVM, stateDB *statedb.StateDB, method *abi.Method, args []interface{}) ([]byte, error) { +func (d *DASignersPrecompile) RegisterSigner( + ctx sdk.Context, + evm *vm.EVM, + stateDB *statedb.StateDB, + contract *vm.Contract, + method *abi.Method, + args []interface{}, +) ([]byte, error) { msg, err := NewMsgRegisterSigner(args) if err != nil { return nil, err } // validation - sender := ToLowerHexWithoutPrefix(evm.Origin) + sender := precopmiles_common.ToLowerHexWithoutPrefix(evm.Origin) if sender != msg.Signer.Account { return nil, fmt.Errorf(ErrInvalidSender, sender, msg.Signer.Account) } + if contract.CallerAddress != evm.Origin { + return nil, fmt.Errorf(precopmiles_common.ErrSenderNotOrigin) + } // execute _, err = d.dasignersKeeper.RegisterSigner(sdk.WrapSDKContext(ctx), msg) if err != nil { @@ -32,11 +44,22 @@ func (d *DASignersPrecompile) RegisterSigner(ctx sdk.Context, evm *vm.EVM, state return method.Outputs.Pack() } -func (d *DASignersPrecompile) RegisterNextEpoch(ctx sdk.Context, evm *vm.EVM, stateDB *statedb.StateDB, method *abi.Method, args []interface{}) ([]byte, error) { - msg, err := NewMsgRegisterNextEpoch(args, ToLowerHexWithoutPrefix(evm.Origin)) +func (d *DASignersPrecompile) RegisterNextEpoch( + ctx sdk.Context, + evm *vm.EVM, + stateDB *statedb.StateDB, + contract *vm.Contract, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + msg, err := NewMsgRegisterNextEpoch(args, precopmiles_common.ToLowerHexWithoutPrefix(evm.Origin)) if err != nil { return nil, err } + // validation + if contract.CallerAddress != evm.Origin { + return nil, fmt.Errorf(precopmiles_common.ErrSenderNotOrigin) + } // execute _, err = d.dasignersKeeper.RegisterNextEpoch(sdk.WrapSDKContext(ctx), msg) if err != nil { @@ -45,11 +68,22 @@ func (d *DASignersPrecompile) RegisterNextEpoch(ctx sdk.Context, evm *vm.EVM, st return method.Outputs.Pack() } -func (d *DASignersPrecompile) UpdateSocket(ctx sdk.Context, evm *vm.EVM, stateDB *statedb.StateDB, method *abi.Method, args []interface{}) ([]byte, error) { - msg, err := NewMsgUpdateSocket(args, ToLowerHexWithoutPrefix(evm.Origin)) +func (d *DASignersPrecompile) UpdateSocket( + ctx sdk.Context, + evm *vm.EVM, + stateDB *statedb.StateDB, + contract *vm.Contract, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + msg, err := NewMsgUpdateSocket(args, precopmiles_common.ToLowerHexWithoutPrefix(evm.Origin)) if err != nil { return nil, err } + // validation + if contract.CallerAddress != evm.Origin { + return nil, fmt.Errorf(precopmiles_common.ErrSenderNotOrigin) + } // execute _, err = d.dasignersKeeper.UpdateSocket(sdk.WrapSDKContext(ctx), msg) if err != nil { diff --git a/precompiles/dasigners/types.go b/precompiles/dasigners/types.go index fdda79ca..89e304df 100644 --- a/precompiles/dasigners/types.go +++ b/precompiles/dasigners/types.go @@ -3,7 +3,6 @@ package dasigners import ( "fmt" "math/big" - "strings" precopmiles_common "github.com/0glabs/0g-chain/precompiles/common" dasignerstypes "github.com/0glabs/0g-chain/x/dasigners/v1/types" @@ -90,7 +89,7 @@ func NewQuerySignerRequest(args []interface{}) (*dasignerstypes.QuerySignerReque Accounts: make([]string, len(accounts)), } for i, account := range accounts { - req.Accounts[i] = ToLowerHexWithoutPrefix(account) + req.Accounts[i] = precopmiles_common.ToLowerHexWithoutPrefix(account) } return &req, nil } @@ -139,10 +138,6 @@ func NewIDASignersSignerDetail(signer *dasignerstypes.Signer) IDASignersSignerDe } } -func ToLowerHexWithoutPrefix(addr common.Address) string { - return strings.ToLower(addr.Hex()[2:]) -} - func NewMsgRegisterSigner(args []interface{}) (*dasignerstypes.MsgRegisterSigner, error) { if len(args) != 2 { return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args)) @@ -151,7 +146,7 @@ func NewMsgRegisterSigner(args []interface{}) (*dasignerstypes.MsgRegisterSigner signer := args[0].(IDASignersSignerDetail) return &dasignerstypes.MsgRegisterSigner{ Signer: &dasignerstypes.Signer{ - Account: ToLowerHexWithoutPrefix(signer.Signer), + Account: precopmiles_common.ToLowerHexWithoutPrefix(signer.Signer), Socket: signer.Socket, PubkeyG1: SerializeG1(signer.PkG1), PubkeyG2: SerializeG2(signer.PkG2), diff --git a/precompiles/interfaces/.solhint.json b/precompiles/interfaces/.solhint.json new file mode 100644 index 00000000..47c4d151 --- /dev/null +++ b/precompiles/interfaces/.solhint.json @@ -0,0 +1,18 @@ +{ + "extends": "solhint:recommended", + "plugins": ["prettier"], + "rules": { + "avoid-low-level-calls": "off", + "compiler-version": "off", + "gas-custom-errors": "off", + "explicit-types": ["warn", "implicit"], + "func-visibility": ["warn", { "ignoreConstructors": true }], + "max-states-count": "off", + "no-empty-blocks": "off", + "no-global-import": "off", + "no-inline-assembly": "off", + "not-rely-on-time": "off", + "prettier/prettier": "error", + "reason-string": "off" + } +} diff --git a/precompiles/interfaces/contracts/IDASigners.sol b/precompiles/interfaces/contracts/IDASigners.sol new file mode 100644 index 00000000..0f83b09e --- /dev/null +++ b/precompiles/interfaces/contracts/IDASigners.sol @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.8.0; + +library BN254 { + struct G1Point { + uint X; + uint Y; + } + + // Encoding of field elements is: X[1] * i + X[0] + struct G2Point { + uint[2] X; + uint[2] Y; + } +} + +interface IDASigners { + /*=== struct ===*/ + struct SignerDetail { + address signer; + string socket; + BN254.G1Point pkG1; + BN254.G2Point pkG2; + } + + struct Params { + uint tokensPerVote; + uint maxVotesPerSigner; + uint maxQuorums; + uint epochBlocks; + uint encodedSlices; + } + + /*=== event ===*/ + event NewSigner( + address indexed signer, + BN254.G1Point pkG1, + BN254.G2Point pkG2 + ); + event SocketUpdated(address indexed signer, string socket); + + /*=== function ===*/ + function params() external view returns (Params memory); + + function epochNumber() external view returns (uint); + + function quorumCount(uint _epoch) external view returns (uint); + + function isSigner(address _account) external view returns (bool); + + function getSigner( + address[] memory _account + ) external view returns (SignerDetail[] memory); + + function getQuorum( + uint _epoch, + uint _quorumId + ) external view returns (address[] memory); + + function getQuorumRow( + uint _epoch, + uint _quorumId, + uint32 _rowIndex + ) external view returns (address); + + function registerSigner( + SignerDetail memory _signer, + BN254.G1Point memory _signature + ) external; + + function updateSocket(string memory _socket) external; + + function registeredEpoch( + address _account, + uint _epoch + ) external view returns (bool); + + function registerNextEpoch(BN254.G1Point memory _signature) external; + + function getAggPkG1( + uint _epoch, + uint _quorumId, + bytes memory _quorumBitmap + ) + external + view + returns (BN254.G1Point memory aggPkG1, uint total, uint hit); +} diff --git a/precompiles/interfaces/contracts/IStaking.sol b/precompiles/interfaces/contracts/IStaking.sol new file mode 100644 index 00000000..39574600 --- /dev/null +++ b/precompiles/interfaces/contracts/IStaking.sol @@ -0,0 +1,415 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.8.0; + +/** + * @dev Description defines a validator description + */ +struct Description { + string moniker; + string identity; + string website; + string securityContact; + string details; +} + +/** + * @dev CommissionRates defines the initial commission rates to be used for creating + * a validator. + */ +struct CommissionRates { + uint rate; // 18 decimals + uint maxRate; // 18 decimals + uint maxChangeRate; // 18 decimals +} + +/** + * @dev Commission defines the commission parameters. + */ +struct Commission { + CommissionRates commissionRates; + uint updateTime; +} + +/** + * @dev Validator defines a validator. + */ +struct Validator { + string operatorAddress; + string consensusPubkey; + bool jailed; + BondStatus status; + uint tokens; + uint delegatorShares; // 18 decimals + Description description; + int64 unbondingHeight; + int64 unbondingTime; + Commission commission; + uint minSelfDelegation; + int64 unbondingOnHoldRefCount; + uint64[] unbondingIds; +} + +/** + * @dev Delegation represents the bond with tokens held by an account. + */ +struct Delegation { + string delegatorAddress; + string validatorAddress; + uint shares; // 18 decimals +} + +/** + * @dev RedelegationResponse is equivalent to a Redelegation except that its entries + * contain a balance in addition to shares which is more suitable for client + * responses. + */ +struct DelegationResponse { + Delegation delegation; + uint balance; +} + +/** + * @dev UnbondingDelegationEntry defines an unbonding object with relevant metadata. + */ +struct UnbondingDelegationEntry { + int64 creationHeight; + int64 completionTime; + uint initialBalance; + uint balance; + uint64 unbondingId; + int64 unbondingOnHoldRefCount; +} + +/** + * @dev UnbondingDelegation stores all of a single delegator's unbonding bonds + * for a single validator in an time-ordered list. + */ +struct UnbondingDelegation { + string delegatorAddress; + string validatorAddress; + UnbondingDelegationEntry[] entries; +} + +/** + * @dev RedelegationResponse is equivalent to a Redelegation except that its entries + * contain a balance in addition to shares which is more suitable for client + * responses. + */ +struct RedelegationResponse { + Redelegation redelegation; + RedelegationEntryResponse[] entries; +} + +/** + * @dev Redelegation contains the list of a particular delegator's redelegating bonds + * from a particular source validator to a particular destination validator. + */ +struct Redelegation { + string delegatorAddress; + string validatorSrcAddress; + string validatorDstAddress; + RedelegationEntry[] entries; +} + +/** + * @dev RedelegationEntry defines a redelegation object with relevant metadata. + */ +struct RedelegationEntry { + int64 creationHeight; + int64 completionTime; + uint initialBalance; + uint sharesDst; // 18 decimals + uint64 unbondingId; + int64 unbondingOnHoldRefCount; +} + +/** + * @dev RedelegationEntryResponse is equivalent to a RedelegationEntry except that it + * contains a balance in addition to shares which is more suitable for client + * responses. + */ +struct RedelegationEntryResponse { + RedelegationEntry redelegationEntry; + uint balance; +} + +/** + * @dev Params defines the parameters for the x/staking module. + */ +struct Params { + int64 unbondingTime; + uint32 maxValidators; + uint32 maxEntries; + uint32 historicalEntries; + string bondDenom; + uint minCommissionRate; // 18 decimals +} + +/** + * @dev BondStatus is the status of a validator. + */ +enum BondStatus { + Unspecified, + Unbonded, + Unbonding, + Bonded +} + +struct NullableUint { + bool isNull; + uint value; +} + +struct PageRequest { + bytes key; + uint64 offset; + uint64 limit; + bool countTotal; + bool reverse; +} + +struct PageResponse { + bytes nextKey; + uint64 total; +} + +interface IStaking { + /*=== cosmos tx ===*/ + + /** + * @dev CreateValidator defines a method for creating a new validator for tx sender. + * cosmos grpc: rpc CreateValidator(MsgCreateValidator) returns (MsgCreateValidatorResponse); + */ + function createValidator( + Description memory description, + CommissionRates memory commission, + uint minSelfDelegation, + string memory pubkey, // 0gchaind tendermint show-validator + uint value + ) external; + + /** + * @dev EditValidator defines a method for editing an existing validator (tx sender). + * cosmos grpc: rpc EditValidator(MsgEditValidator) returns (MsgEditValidatorResponse); + */ + function editValidator( + Description memory description, + NullableUint memory commissionRate, + NullableUint memory minSelfDelegation + ) external; + + /** + * @dev Delegate defines a method for performing a delegation of coins from a delegator to a validator.abi + * The delegator is tx sender. + * cosmos grpc: rpc Delegate(MsgDelegate) returns (MsgDelegateResponse); + */ + function delegate( + string memory validatorAddress, + uint amount // in bond denom + ) external; + + /** + * @dev BeginRedelegate defines a method for performing a redelegationA + * of coins from a delegator and source validator to a destination validator. + * The delegator is tx sender. + * cosmos grpc: rpc BeginRedelegate(MsgBeginRedelegate) returns (MsgBeginRedelegateResponse); + */ + function beginRedelegate( + string memory validatorSrcAddress, + string memory validatorDstAddress, + uint amount // in bond denom + ) external returns (uint completionTime); + + /** + * @dev Undelegate defines a method for performing an undelegation from a + * delegate and a validator. + * The delegator is tx sender. + * cosmos grpc: rpc Undelegate(MsgUndelegate) returns (MsgUndelegateResponse); + */ + function undelegate( + string memory validatorAddress, + uint amount // in bond denom + ) external returns (uint completionTime); + + /** + * @dev CancelUnbondingDelegation defines a method for performing canceling the unbonding delegation + * and delegate back to previous validator. + * The delegator is tx sender. + * Since: cosmos-sdk 0.46 + * cosmos grpc: rpc CancelUnbondingDelegation(MsgCancelUnbondingDelegation) returns (MsgCancelUnbondingDelegationResponse); + */ + function cancelUnbondingDelegation( + string memory validatorAddress, + uint amount, // in bond denom + uint creationHeight + ) external; + + /** + * @dev UpdateParams defines an operation for updating the x/staking module parameters. + * Since: cosmos-sdk 0.47 + * grpc: rpc UpdateParams(MsgUpdateParams) returns (MsgUpdateParamsResponse); + */ + // Skipped. This function is controlled by governance module. + + /*=== cosmos query ===*/ + + /** + * @dev Validators queries all validators that match the given status. + * cosmos grpc: rpc Validators(QueryValidatorsRequest) returns (QueryValidatorsResponse); + */ + function validators( + string memory status, + PageRequest memory pagination + ) + external + view + returns ( + Validator[] memory validators, + PageResponse memory paginationResult + ); + + /** + * @dev Validator queries validator info for given validator address. + * cosmos grpc: rpc Validator(QueryValidatorRequest) returns (QueryValidatorResponse); + */ + function validator( + string memory validatorAddress + ) external view returns (Validator memory validator); + + /** + * @dev ValidatorDelegations queries delegate info for given validator. + * cosmos grpc: rpc ValidatorDelegations(QueryValidatorDelegationsRequest) returns (QueryValidatorDelegationsResponse); + */ + function validatorDelegations( + string memory validatorAddr, + PageRequest memory pagination + ) + external + view + returns ( + DelegationResponse[] memory delegationResponses, + PageResponse memory paginationResult + ); + + /** + * @dev ValidatorUnbondingDelegations queries unbonding delegations of a validator. + * cosmos grpc: rpc ValidatorUnbondingDelegations(QueryValidatorUnbondingDelegationsRequest) returns (QueryValidatorUnbondingDelegationsResponse); + */ + // + function validatorUnbondingDelegations( + string memory validatorAddr, + PageRequest memory pagination + ) + external + view + returns ( + UnbondingDelegation[] memory unbondingResponses, + PageResponse memory paginationResult + ); + + /** + * @dev Delegation queries delegate info for given validator delegator pair. + * cosmos grpc: rpc Delegation(QueryDelegationRequest) returns (QueryDelegationResponse); + */ + function delegation( + string memory delegatorAddr, + string memory validatorAddr + ) external view returns (Delegation memory delegation, uint balance); + + /** + * @dev UnbondingDelegation queries unbonding info for given validator delegator pair. + * cosmos grpc: rpc UnbondingDelegation(QueryUnbondingDelegationRequest) returns (QueryUnbondingDelegationResponse); + */ + function unbondingDelegation( + string memory delegatorAddr, + string memory validatorAddr + ) external view returns (UnbondingDelegation memory unbond); + + /** + * @dev DelegatorDelegations queries all delegations of a given delegator address. + * + * cosmos grpc: rpc DelegatorDelegations(QueryDelegatorDelegationsRequest) returns (QueryDelegatorDelegationsResponse); + */ + function delegatorDelegations( + string memory delegatorAddr, + PageRequest memory pagination + ) + external + view + returns ( + DelegationResponse[] memory delegationResponses, + PageResponse memory paginationResult + ); + + /** + * @dev DelegatorUnbondingDelegations queries all unbonding delegations of a given delegator address. + * cosmos grpc: rpc DelegatorUnbondingDelegations(QueryDelegatorUnbondingDelegationsRequest) + */ + function delegatorUnbondingDelegations( + string memory delegatorAddr, + PageRequest memory pagination + ) + external + view + returns ( + UnbondingDelegation[] memory unbondingResponses, + PageResponse memory paginationResult + ); + + /** + * @dev Redelegations queries redelegations of given address. + * + * grpc: rpc Redelegations(QueryRedelegationsRequest) returns (QueryRedelegationsResponse); + */ + function redelegations( + string memory delegatorAddress, + string memory srcValidatorAddress, + string memory dstValidatorAddress, + PageRequest calldata pageRequest + ) + external + view + returns ( + RedelegationResponse[] calldata redelegationResponses, + PageResponse calldata paginationResult + ); + + /** + * @dev DelegatorValidators queries all validators info for given delegator address. + * cosmos grpc: rpc DelegatorValidators(QueryDelegatorValidatorsRequest) returns (QueryDelegatorValidatorsResponse); + */ + function delegatorValidators( + string memory delegatorAddr, + PageRequest memory pagination + ) + external + view + returns ( + Validator[] memory validators, + PageResponse memory paginationResult + ); + + /** + * @dev DelegatorValidator queries validator info for given delegator validator pair. + * cosmos grpc: rpc DelegatorValidator(QueryDelegatorValidatorRequest) returns (QueryDelegatorValidatorResponse); + */ + function delegatorValidator( + string memory delegatorAddr, + string memory validatorAddr + ) external view returns (Validator memory validator); + + /** + * @dev Pool queries the pool info. + * cosmos grpc: rpc Pool(QueryPoolRequest) returns (QueryPoolResponse); + */ + function pool() + external + view + returns (uint notBondedTokens, uint bondedTokens); + + /** + * @dev Parameters queries the staking parameters. + * cosmos grpc: rpc Params(QueryParamsRequest) returns (QueryParamsResponse); + */ + function params() external view returns (Params memory params); +} diff --git a/precompiles/interfaces/hardhat.config.ts b/precompiles/interfaces/hardhat.config.ts new file mode 100644 index 00000000..43757e6a --- /dev/null +++ b/precompiles/interfaces/hardhat.config.ts @@ -0,0 +1,33 @@ +import "hardhat-abi-exporter"; +import { HardhatUserConfig } from "hardhat/types"; + +const config: HardhatUserConfig = { + paths: { + artifacts: "build/artifacts", + cache: "build/cache", + sources: "contracts", + }, + solidity: { + compilers: [ + { + version: "0.8.20", + settings: { + evmVersion: "istanbul", + optimizer: { + enabled: true, + runs: 200, + }, + }, + }, + ], + }, + abiExporter: { + path: "./abis", + runOnCompile: true, + clear: true, + flat: true, + format: "json", + }, +}; + +export default config; diff --git a/precompiles/interfaces/package.json b/precompiles/interfaces/package.json new file mode 100644 index 00000000..b144f19b --- /dev/null +++ b/precompiles/interfaces/package.json @@ -0,0 +1,27 @@ +{ + "name": "precompile-contracts", + "version": "1.0.0", + "license": "MIT", + "scripts": { + "build": "hardhat compile", + "fmt:sol": "prettier 'contracts/**/*.sol' -w" + }, + "devDependencies": { + "@nomicfoundation/hardhat-ethers": "^3.0.5", + "@typescript-eslint/eslint-plugin": "6.21.0", + "@typescript-eslint/parser": "6.21.0", + "eslint": "8.34.0", + "eslint-config-prettier": "8.6.0", + "eslint-plugin-no-only-tests": "3.1.0", + "eslint-plugin-prettier": "4.2.1", + "hardhat": "^2.22.2", + "hardhat-abi-exporter": "^2.10.1", + "prettier": "2.8.4", + "prettier-plugin-organize-imports": "3.2.4", + "prettier-plugin-solidity": "1.1.2", + "solhint": "^4.5.4", + "solhint-plugin-prettier": "0.0.5", + "ts-node": "^10.9.2", + "typescript": "4.9.5" + } +} diff --git a/precompiles/interfaces/yarn.lock b/precompiles/interfaces/yarn.lock new file mode 100644 index 00000000..6f74526d --- /dev/null +++ b/precompiles/interfaces/yarn.lock @@ -0,0 +1,3152 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/code-frame@^7.0.0": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.25.9.tgz#895b6c7e04a7271a0cbfd575d2e8131751914cc7" + integrity sha512-z88xeGxnzehn2sqZ8UdGQEvYErF1odv2CftxInpSYJt6uHuPe9YjahKZITGs3l5LeI9d2ROG+obuDAoSlqbNfQ== + dependencies: + "@babel/highlight" "^7.25.9" + picocolors "^1.0.0" + +"@babel/helper-validator-identifier@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7" + integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== + +"@babel/highlight@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.25.9.tgz#8141ce68fc73757946f983b343f1231f4691acc6" + integrity sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw== + dependencies: + "@babel/helper-validator-identifier" "^7.25.9" + chalk "^2.4.2" + js-tokens "^4.0.0" + picocolors "^1.0.0" + +"@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" + +"@eslint-community/eslint-utils@^4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.5.1": + version "4.11.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.11.1.tgz#a547badfc719eb3e5f4b556325e542fbe9d7a18f" + integrity sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q== + +"@eslint/eslintrc@^1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.4.1.tgz#af58772019a2d271b7e2d4c23ff4ddcba3ccfb3e" + integrity sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^9.4.0" + globals "^13.19.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.5.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" + integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/abstract-provider@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef" + integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + +"@ethersproject/abstract-signer@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2" + integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/address@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" + integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + +"@ethersproject/base64@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c" + integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + +"@ethersproject/bignumber@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" + integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + bn.js "^5.2.1" + +"@ethersproject/bytes@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" + integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/constants@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" + integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + +"@ethersproject/hash@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" + integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/keccak256@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" + integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + js-sha3 "0.8.0" + +"@ethersproject/logger@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" + integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== + +"@ethersproject/networks@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6" + integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/properties@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" + integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/rlp@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304" + integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/signing-key@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3" + integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + bn.js "^5.2.1" + elliptic "6.5.4" + hash.js "1.1.7" + +"@ethersproject/strings@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" + integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/transactions@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b" + integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + +"@ethersproject/web@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae" + integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w== + dependencies: + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@fastify/busboy@^2.0.0": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.1.tgz#b9da6a878a371829a0502c9b6c1c143ef6663f4d" + integrity sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA== + +"@humanwhocodes/config-array@^0.11.8": + version "0.11.14" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" + integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg== + dependencies: + "@humanwhocodes/object-schema" "^2.0.2" + debug "^4.3.1" + minimatch "^3.0.5" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/object-schema@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" + integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== + +"@jridgewell/resolve-uri@^3.0.3": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== + +"@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" + +"@metamask/eth-sig-util@^4.0.0": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz#3ad61f6ea9ad73ba5b19db780d40d9aae5157088" + integrity sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ== + dependencies: + ethereumjs-abi "^0.6.8" + ethereumjs-util "^6.2.1" + ethjs-util "^0.1.6" + tweetnacl "^1.0.3" + tweetnacl-util "^0.15.1" + +"@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" + integrity sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ== + +"@noble/secp256k1@1.7.1", "@noble/secp256k1@~1.7.0": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.1.tgz#b251c70f824ce3ca7f8dc3df08d58f005cc0507c" + integrity sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw== + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@nomicfoundation/edr-darwin-arm64@0.6.4": + version "0.6.4" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.6.4.tgz#6eaa64a6ea5201e4c92b121f2b7fd197b26e450a" + integrity sha512-QNQErISLgssV9+qia8sIjRANqtbW8snSDvjspixT/kSQ5ZSGxxctTg7x72wPSrcu8+EBEveIe5uqENIp5GH8HQ== + +"@nomicfoundation/edr-darwin-x64@0.6.4": + version "0.6.4" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.6.4.tgz#d15ca89e9deef7d0a710cf90e79f3cc270a5a999" + integrity sha512-cjVmREiwByyc9+oGfvAh49IAw+oVJHF9WWYRD+Tm/ZlSpnEVWxrGNBak2bd/JSYjn+mZE7gmWS4SMRi4nKaLUg== + +"@nomicfoundation/edr-linux-arm64-gnu@0.6.4": + version "0.6.4" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.6.4.tgz#e73c41ca015dfddb5f4cb6cd3d9b2cbe5cc28989" + integrity sha512-96o9kRIVD6W5VkgKvUOGpWyUGInVQ5BRlME2Fa36YoNsRQMaKtmYJEU0ACosYES6ZTpYC8U5sjMulvPtVoEfOA== + +"@nomicfoundation/edr-linux-arm64-musl@0.6.4": + version "0.6.4" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.6.4.tgz#90906f733e4ad26657baeb22d28855d934ab7541" + integrity sha512-+JVEW9e5plHrUfQlSgkEj/UONrIU6rADTEk+Yp9pbe+mzNkJdfJYhs5JYiLQRP4OjxH4QOrXI97bKU6FcEbt5Q== + +"@nomicfoundation/edr-linux-x64-gnu@0.6.4": + version "0.6.4" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.6.4.tgz#11b8bd73df145a192e5a08199e5e81995fcde502" + integrity sha512-nzYWW+fO3EZItOeP4CrdMgDXfaGBIBkKg0Y/7ySpUxLqzut40O4Mb0/+quqLAFkacUSWMlFp8nsmypJfOH5zoA== + +"@nomicfoundation/edr-linux-x64-musl@0.6.4": + version "0.6.4" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.6.4.tgz#a34b9a2c9e34853207824dc81622668a069ca642" + integrity sha512-QFRoE9qSQ2boRrVeQ1HdzU+XN7NUgwZ1SIy5DQt4d7jCP+5qTNsq8LBNcqhRBOATgO63nsweNUhxX/Suj5r1Sw== + +"@nomicfoundation/edr-win32-x64-msvc@0.6.4": + version "0.6.4" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.6.4.tgz#ca035c6f66ae9f88fa3ef123a1f3a2099cce7a5a" + integrity sha512-2yopjelNkkCvIjUgBGhrn153IBPLwnsDeNiq6oA0WkeM8tGmQi4td+PGi9jAriUDAkc59Yoi2q9hYA6efiY7Zw== + +"@nomicfoundation/edr@^0.6.4": + version "0.6.4" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr/-/edr-0.6.4.tgz#1cd336c46a60f5af774e6cf0f1943f49f63dded6" + integrity sha512-YgrSuT3yo5ZQkbvBGqQ7hG+RDvz3YygSkddg4tb1Z0Y6pLXFzwrcEwWaJCFAVeeZxdxGfCgGMUYgRVneK+WXkw== + dependencies: + "@nomicfoundation/edr-darwin-arm64" "0.6.4" + "@nomicfoundation/edr-darwin-x64" "0.6.4" + "@nomicfoundation/edr-linux-arm64-gnu" "0.6.4" + "@nomicfoundation/edr-linux-arm64-musl" "0.6.4" + "@nomicfoundation/edr-linux-x64-gnu" "0.6.4" + "@nomicfoundation/edr-linux-x64-musl" "0.6.4" + "@nomicfoundation/edr-win32-x64-msvc" "0.6.4" + +"@nomicfoundation/ethereumjs-common@4.0.4": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.4.tgz#9901f513af2d4802da87c66d6f255b510bef5acb" + integrity sha512-9Rgb658lcWsjiicr5GzNCjI1llow/7r0k50dLL95OJ+6iZJcVbi15r3Y0xh2cIO+zgX0WIHcbzIu6FeQf9KPrg== + dependencies: + "@nomicfoundation/ethereumjs-util" "9.0.4" + +"@nomicfoundation/ethereumjs-rlp@5.0.4": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.4.tgz#66c95256fc3c909f6fb18f6a586475fc9762fa30" + integrity sha512-8H1S3s8F6QueOc/X92SdrA4RDenpiAEqMg5vJH99kcQaCy/a3Q6fgseo75mgWlbanGJXSlAPtnCeG9jvfTYXlw== + +"@nomicfoundation/ethereumjs-tx@5.0.4": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.4.tgz#b0ceb58c98cc34367d40a30d255d6315b2f456da" + integrity sha512-Xjv8wAKJGMrP1f0n2PeyfFCCojHd7iS3s/Ab7qzF1S64kxZ8Z22LCMynArYsVqiFx6rzYy548HNVEyI+AYN/kw== + dependencies: + "@nomicfoundation/ethereumjs-common" "4.0.4" + "@nomicfoundation/ethereumjs-rlp" "5.0.4" + "@nomicfoundation/ethereumjs-util" "9.0.4" + ethereum-cryptography "0.1.3" + +"@nomicfoundation/ethereumjs-util@9.0.4": + version "9.0.4" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.4.tgz#84c5274e82018b154244c877b76bc049a4ed7b38" + integrity sha512-sLOzjnSrlx9Bb9EFNtHzK/FJFsfg2re6bsGqinFinH1gCqVfz9YYlXiMWwDM4C/L4ywuHFCYwfKTVr/QHQcU0Q== + dependencies: + "@nomicfoundation/ethereumjs-rlp" "5.0.4" + ethereum-cryptography "0.1.3" + +"@nomicfoundation/hardhat-ethers@^3.0.5": + version "3.0.8" + resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-ethers/-/hardhat-ethers-3.0.8.tgz#af078f566373abeb77e11cbe69fe3dd47f8bfc27" + integrity sha512-zhOZ4hdRORls31DTOqg+GmEZM0ujly8GGIuRY7t7szEk2zW/arY1qDug/py8AEktT00v5K+b6RvbVog+va51IA== + dependencies: + debug "^4.1.1" + lodash.isequal "^4.5.0" + +"@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.2.tgz#3a9c3b20d51360b20affb8f753e756d553d49557" + integrity sha512-JaqcWPDZENCvm++lFFGjrDd8mxtf+CtLd2MiXvMNTBD33dContTZ9TWETwNFwg7JTJT5Q9HEecH7FA+HTSsIUw== + +"@nomicfoundation/solidity-analyzer-darwin-x64@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-x64/-/solidity-analyzer-darwin-x64-0.1.2.tgz#74dcfabeb4ca373d95bd0d13692f44fcef133c28" + integrity sha512-fZNmVztrSXC03e9RONBT+CiksSeYcxI1wlzqyr0L7hsQlK1fzV+f04g2JtQ1c/Fe74ZwdV6aQBdd6Uwl1052sw== + +"@nomicfoundation/solidity-analyzer-linux-arm64-gnu@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-gnu/-/solidity-analyzer-linux-arm64-gnu-0.1.2.tgz#4af5849a89e5a8f511acc04f28eb5d4460ba2b6a" + integrity sha512-3d54oc+9ZVBuB6nbp8wHylk4xh0N0Gc+bk+/uJae+rUgbOBwQSfuGIbAZt1wBXs5REkSmynEGcqx6DutoK0tPA== + +"@nomicfoundation/solidity-analyzer-linux-arm64-musl@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-musl/-/solidity-analyzer-linux-arm64-musl-0.1.2.tgz#54036808a9a327b2ff84446c130a6687ee702a8e" + integrity sha512-iDJfR2qf55vgsg7BtJa7iPiFAsYf2d0Tv/0B+vhtnI16+wfQeTbP7teookbGvAo0eJo7aLLm0xfS/GTkvHIucA== + +"@nomicfoundation/solidity-analyzer-linux-x64-gnu@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-gnu/-/solidity-analyzer-linux-x64-gnu-0.1.2.tgz#466cda0d6e43691986c944b909fc6dbb8cfc594e" + integrity sha512-9dlHMAt5/2cpWyuJ9fQNOUXFB/vgSFORg1jpjX1Mh9hJ/MfZXlDdHQ+DpFCs32Zk5pxRBb07yGvSHk9/fezL+g== + +"@nomicfoundation/solidity-analyzer-linux-x64-musl@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-musl/-/solidity-analyzer-linux-x64-musl-0.1.2.tgz#2b35826987a6e94444140ac92310baa088ee7f94" + integrity sha512-GzzVeeJob3lfrSlDKQw2bRJ8rBf6mEYaWY+gW0JnTDHINA0s2gPR4km5RLIj1xeZZOYz4zRw+AEeYgLRqB2NXg== + +"@nomicfoundation/solidity-analyzer-win32-x64-msvc@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-x64-msvc/-/solidity-analyzer-win32-x64-msvc-0.1.2.tgz#e6363d13b8709ca66f330562337dbc01ce8bbbd9" + integrity sha512-Fdjli4DCcFHb4Zgsz0uEJXZ2K7VEO+w5KVv7HmT7WO10iODdU9csC2az4jrhEsRtiR9Gfd74FlG0NYlw1BMdyA== + +"@nomicfoundation/solidity-analyzer@^0.1.0": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.2.tgz#8bcea7d300157bf3a770a851d9f5c5e2db34ac55" + integrity sha512-q4n32/FNKIhQ3zQGGw5CvPF6GTvDCpYwIf7bEY/dZTZbgfDsHyjJwURxUJf3VQuuJj+fDIFl4+KkBVbw4Ef6jA== + optionalDependencies: + "@nomicfoundation/solidity-analyzer-darwin-arm64" "0.1.2" + "@nomicfoundation/solidity-analyzer-darwin-x64" "0.1.2" + "@nomicfoundation/solidity-analyzer-linux-arm64-gnu" "0.1.2" + "@nomicfoundation/solidity-analyzer-linux-arm64-musl" "0.1.2" + "@nomicfoundation/solidity-analyzer-linux-x64-gnu" "0.1.2" + "@nomicfoundation/solidity-analyzer-linux-x64-musl" "0.1.2" + "@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.2" + +"@pnpm/config.env-replace@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz#ab29da53df41e8948a00f2433f085f54de8b3a4c" + integrity sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w== + +"@pnpm/network.ca-file@^1.0.1": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz#2ab05e09c1af0cdf2fcf5035bea1484e222f7983" + integrity sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA== + dependencies: + graceful-fs "4.2.10" + +"@pnpm/npm-conf@^2.1.0": + version "2.3.1" + resolved "https://registry.yarnpkg.com/@pnpm/npm-conf/-/npm-conf-2.3.1.tgz#bb375a571a0bd63ab0a23bece33033c683e9b6b0" + integrity sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw== + dependencies: + "@pnpm/config.env-replace" "^1.1.0" + "@pnpm/network.ca-file" "^1.0.1" + config-chain "^1.1.11" + +"@scure/base@~1.1.0": + version "1.1.9" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.9.tgz#e5e142fbbfe251091f9c5f1dd4c834ac04c3dbd1" + integrity sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg== + +"@scure/bip32@1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.1.5.tgz#d2ccae16dcc2e75bc1d75f5ef3c66a338d1ba300" + integrity sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw== + dependencies: + "@noble/hashes" "~1.2.0" + "@noble/secp256k1" "~1.7.0" + "@scure/base" "~1.1.0" + +"@scure/bip39@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.1.tgz#b54557b2e86214319405db819c4b6a370cf340c5" + integrity sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg== + dependencies: + "@noble/hashes" "~1.2.0" + "@scure/base" "~1.1.0" + +"@sentry/core@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" + integrity sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/minimal" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/hub@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.30.0.tgz#2453be9b9cb903404366e198bd30c7ca74cdc100" + integrity sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ== + dependencies: + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/minimal@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.30.0.tgz#ce3d3a6a273428e0084adcb800bc12e72d34637b" + integrity sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/types" "5.30.0" + tslib "^1.9.3" + +"@sentry/node@^5.18.1": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.30.0.tgz#4ca479e799b1021285d7fe12ac0858951c11cd48" + integrity sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg== + dependencies: + "@sentry/core" "5.30.0" + "@sentry/hub" "5.30.0" + "@sentry/tracing" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + cookie "^0.4.1" + https-proxy-agent "^5.0.0" + lru_map "^0.3.3" + tslib "^1.9.3" + +"@sentry/tracing@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-5.30.0.tgz#501d21f00c3f3be7f7635d8710da70d9419d4e1f" + integrity sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/minimal" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/types@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.30.0.tgz#19709bbe12a1a0115bc790b8942917da5636f402" + integrity sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw== + +"@sentry/utils@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.30.0.tgz#9a5bd7ccff85ccfe7856d493bffa64cabc41e980" + integrity sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww== + dependencies: + "@sentry/types" "5.30.0" + tslib "^1.9.3" + +"@sindresorhus/is@^5.2.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-5.6.0.tgz#41dd6093d34652cddb5d5bdeee04eafc33826668" + integrity sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g== + +"@solidity-parser/parser@^0.15.0": + version "0.15.0" + resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.15.0.tgz#1d359be40be84f174dd616ccfadcf43346c6bf63" + integrity sha512-5UFJJTzWi1hgFk6aGCZ5rxG2DJkCJOzJ74qg7UkWSNCDSigW+CJLoYUb5bLiKrtI34Nr9rpFSUNHfkqtlL+N/w== + dependencies: + antlr4ts "^0.5.0-alpha.4" + +"@solidity-parser/parser@^0.18.0": + version "0.18.0" + resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.18.0.tgz#8e77a02a09ecce957255a2f48c9a7178ec191908" + integrity sha512-yfORGUIPgLck41qyN7nbwJRAx17/jAIXCTanHOJZhB6PJ1iAk/84b/xlsVKFSyNyLXIj0dhppoE0+CRws7wlzA== + +"@szmarczak/http-timer@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-5.0.1.tgz#c7c1bf1141cdd4751b0399c8fc7b8b664cd5be3a" + integrity sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw== + dependencies: + defer-to-connect "^2.0.1" + +"@tsconfig/node10@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2" + integrity sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw== + +"@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.4" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== + +"@types/bn.js@^4.11.3": + version "4.11.6" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" + integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== + dependencies: + "@types/node" "*" + +"@types/bn.js@^5.1.0": + version "5.1.6" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.6.tgz#9ba818eec0c85e4d3c679518428afdf611d03203" + integrity sha512-Xh8vSwUeMKeYYrj3cX4lGQgFSF/N03r+tv4AiLl1SucqV+uTQpxRcnM8AkXKHwYP9ZPXOYXRr2KPXpVlIvqh9w== + dependencies: + "@types/node" "*" + +"@types/http-cache-semantics@^4.0.2": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz#b979ebad3919799c979b17c72621c0bc0a31c6c4" + integrity sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA== + +"@types/json-schema@^7.0.12": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + +"@types/lru-cache@^5.1.0": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.1.tgz#c48c2e27b65d2a153b19bfc1a317e30872e01eef" + integrity sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw== + +"@types/node@*": + version "22.7.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.7.9.tgz#2bf2797b5e84702d8262ea2cf843c3c3c880d0e9" + integrity sha512-jrTfRC7FM6nChvU7X2KqcrgquofrWLFDeYC1hKfwNWomVvrn7JIksqf344WN2X/y8xrgqBd2dJATZV4GbatBfg== + dependencies: + undici-types "~6.19.2" + +"@types/pbkdf2@^3.0.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.2.tgz#2dc43808e9985a2c69ff02e2d2027bd4fe33e8dc" + integrity sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew== + dependencies: + "@types/node" "*" + +"@types/secp256k1@^4.0.1": + version "4.0.6" + resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.6.tgz#d60ba2349a51c2cbc5e816dcd831a42029d376bf" + integrity sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ== + dependencies: + "@types/node" "*" + +"@types/semver@^7.5.0": + version "7.5.8" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" + integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== + +"@typescript-eslint/eslint-plugin@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz#30830c1ca81fd5f3c2714e524c4303e0194f9cd3" + integrity sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA== + dependencies: + "@eslint-community/regexpp" "^4.5.1" + "@typescript-eslint/scope-manager" "6.21.0" + "@typescript-eslint/type-utils" "6.21.0" + "@typescript-eslint/utils" "6.21.0" + "@typescript-eslint/visitor-keys" "6.21.0" + debug "^4.3.4" + graphemer "^1.4.0" + ignore "^5.2.4" + natural-compare "^1.4.0" + semver "^7.5.4" + ts-api-utils "^1.0.1" + +"@typescript-eslint/parser@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.21.0.tgz#af8fcf66feee2edc86bc5d1cf45e33b0630bf35b" + integrity sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ== + dependencies: + "@typescript-eslint/scope-manager" "6.21.0" + "@typescript-eslint/types" "6.21.0" + "@typescript-eslint/typescript-estree" "6.21.0" + "@typescript-eslint/visitor-keys" "6.21.0" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz#ea8a9bfc8f1504a6ac5d59a6df308d3a0630a2b1" + integrity sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg== + dependencies: + "@typescript-eslint/types" "6.21.0" + "@typescript-eslint/visitor-keys" "6.21.0" + +"@typescript-eslint/type-utils@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz#6473281cfed4dacabe8004e8521cee0bd9d4c01e" + integrity sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag== + dependencies: + "@typescript-eslint/typescript-estree" "6.21.0" + "@typescript-eslint/utils" "6.21.0" + debug "^4.3.4" + ts-api-utils "^1.0.1" + +"@typescript-eslint/types@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.21.0.tgz#205724c5123a8fef7ecd195075fa6e85bac3436d" + integrity sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg== + +"@typescript-eslint/typescript-estree@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz#c47ae7901db3b8bddc3ecd73daff2d0895688c46" + integrity sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ== + dependencies: + "@typescript-eslint/types" "6.21.0" + "@typescript-eslint/visitor-keys" "6.21.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + minimatch "9.0.3" + semver "^7.5.4" + ts-api-utils "^1.0.1" + +"@typescript-eslint/utils@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.21.0.tgz#4714e7a6b39e773c1c8e97ec587f520840cd8134" + integrity sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ== + dependencies: + "@eslint-community/eslint-utils" "^4.4.0" + "@types/json-schema" "^7.0.12" + "@types/semver" "^7.5.0" + "@typescript-eslint/scope-manager" "6.21.0" + "@typescript-eslint/types" "6.21.0" + "@typescript-eslint/typescript-estree" "6.21.0" + semver "^7.5.4" + +"@typescript-eslint/visitor-keys@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz#87a99d077aa507e20e238b11d56cc26ade45fe47" + integrity sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A== + dependencies: + "@typescript-eslint/types" "6.21.0" + eslint-visitor-keys "^3.4.1" + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn-walk@^8.1.1: + version "8.3.4" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.4.tgz#794dd169c3977edf4ba4ea47583587c5866236b7" + integrity sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g== + dependencies: + acorn "^8.11.0" + +acorn@^8.11.0, acorn@^8.4.1, acorn@^8.9.0: + version "8.13.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.13.0.tgz#2a30d670818ad16ddd6a35d3842dacec9e5d7ca3" + integrity sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w== + +adm-zip@^0.4.16: + version "0.4.16" + resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.16.tgz#cf4c508fdffab02c269cbc7f471a875f05570365" + integrity sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg== + +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + +ajv@^6.10.0, ajv@^6.12.4, ajv@^6.12.6: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^8.0.1: + version "8.17.1" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" + integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== + dependencies: + fast-deep-equal "^3.1.3" + fast-uri "^3.0.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + +ansi-align@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" + integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== + dependencies: + string-width "^4.1.0" + +ansi-colors@^4.1.0, ansi-colors@^4.1.1, ansi-colors@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" + integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== + +ansi-escapes@^4.3.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +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@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.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" + +antlr4@^4.13.1-patch-1: + version "4.13.2" + resolved "https://registry.yarnpkg.com/antlr4/-/antlr4-4.13.2.tgz#0d084ad0e32620482a9c3a0e2470c02e72e4006d" + integrity sha512-QiVbZhyy4xAZ17UPEuG3YTOt8ZaoeOR1CvEAqrEsDBsOqINslaB147i9xqljZqoyf5S+EUlGStaj+t22LT9MOg== + +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== + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +ast-parents@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/ast-parents/-/ast-parents-0.0.1.tgz#508fd0f05d0c48775d9eccda2e174423261e8dd3" + integrity sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA== + +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base-x@^3.0.2: + version "3.0.10" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.10.tgz#62de58653f8762b5d6f8d9fe30fa75f7b2585a75" + integrity sha512-7d0s06rR9rYaIWHkpfLIFICM/tkSVdoPC9qYAQRpxn9DdKNWNsKC0uk++akckyLq16Tx2WIinnZ6WRriAt6njQ== + dependencies: + safe-buffer "^5.0.1" + +binary-extensions@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== + +blakejs@^1.1.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814" + integrity sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ== + +bn.js@^4.11.0, bn.js@^4.11.8, bn.js@^4.11.9: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +bn.js@^5.2.0, bn.js@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + +boxen@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" + integrity sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ== + dependencies: + ansi-align "^3.0.0" + camelcase "^6.2.0" + chalk "^4.1.0" + cli-boxes "^2.2.1" + string-width "^4.2.2" + type-fest "^0.20.2" + widest-line "^3.1.0" + wrap-ansi "^7.0.0" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.3, braces@~3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== + +browser-stdout@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +browserify-aes@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== + dependencies: + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +bs58@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" + integrity sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw== + dependencies: + base-x "^3.0.2" + +bs58check@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" + integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== + dependencies: + bs58 "^4.0.0" + create-hash "^1.1.0" + safe-buffer "^5.1.2" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +cacheable-lookup@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz#3476a8215d046e5a3202a9209dd13fec1f933a27" + integrity sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w== + +cacheable-request@^10.2.8: + version "10.2.14" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-10.2.14.tgz#eb915b665fda41b79652782df3f553449c406b9d" + integrity sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ== + dependencies: + "@types/http-cache-semantics" "^4.0.2" + get-stream "^6.0.1" + http-cache-semantics "^4.1.1" + keyv "^4.5.3" + mimic-response "^4.0.0" + normalize-url "^8.0.0" + responselike "^3.0.0" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase@^6.0.0, camelcase@^6.2.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chokidar@^3.5.3: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chokidar@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-4.0.1.tgz#4a6dff66798fb0f72a94f616abbd7e1a19f31d41" + integrity sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA== + dependencies: + readdirp "^4.0.1" + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +cli-boxes@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" + integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +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.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +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== + +command-exists@^1.2.8: + version "1.2.9" + resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" + integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== + +commander@^10.0.0: + version "10.0.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" + integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== + +commander@^8.1.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" + integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +config-chain@^1.1.11: + version "1.1.13" + resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.13.tgz#fad0795aa6a6cdaff9ed1b68e9dff94372c232f4" + integrity sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ== + dependencies: + ini "^1.3.4" + proto-list "~1.2.1" + +cookie@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== + +cosmiconfig@^8.0.0: + version "8.3.6" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.3.6.tgz#060a2b871d66dba6c8538ea1118ba1ac16f5fae3" + integrity sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA== + dependencies: + import-fresh "^3.3.0" + js-yaml "^4.1.0" + parse-json "^5.2.0" + path-type "^4.0.0" + +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +create-hmac@^1.1.4, create-hmac@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +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-spawn@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +debug@4, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.5: + version "4.3.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" + integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== + dependencies: + ms "^2.1.3" + +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + +decompress-response@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" + integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== + dependencies: + mimic-response "^3.1.0" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +defer-to-connect@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" + integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== + +delete-empty@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/delete-empty/-/delete-empty-3.0.0.tgz#f8040f2669f26fa7060bc2304e9859c593b685e8" + integrity sha512-ZUyiwo76W+DYnKsL3Kim6M/UOavPdBJgDYWOmuQhYaZvJH0AXAHbUNyEDtRbBra8wqqr686+63/0azfEk1ebUQ== + dependencies: + ansi-colors "^4.1.0" + minimist "^1.2.0" + path-starts-with "^2.0.0" + rimraf "^2.6.2" + +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +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== + +diff@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" + integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +elliptic@6.5.4: + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +elliptic@^6.5.2, elliptic@^6.5.7: + version "6.5.7" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.7.tgz#8ec4da2cb2939926a1b9a73619d768207e647c8b" + integrity sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.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== + +enquirer@^2.3.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.4.1.tgz#93334b3fbd74fc7097b224ab4a8fb7e40bf4ae56" + integrity sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ== + dependencies: + ansi-colors "^4.1.1" + strip-ansi "^6.0.1" + +env-paths@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" + integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== + +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +escalade@^3.1.1: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-config-prettier@8.6.0: + version "8.6.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.6.0.tgz#dec1d29ab728f4fa63061774e1672ac4e363d207" + integrity sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA== + +eslint-plugin-no-only-tests@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-no-only-tests/-/eslint-plugin-no-only-tests-3.1.0.tgz#f38e4935c6c6c4842bf158b64aaa20c366fe171b" + integrity sha512-Lf4YW/bL6Un1R6A76pRZyE1dl1vr31G/ev8UzIc/geCgFWyrKil8hVjYqWVKGB/UIGmb6Slzs9T0wNezdSVegw== + +eslint-plugin-prettier@4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz#651cbb88b1dab98bfd42f017a12fa6b2d993f94b" + integrity sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ== + dependencies: + prettier-linter-helpers "^1.0.0" + +eslint-scope@^7.1.1: + version "7.2.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" + integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" + integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== + dependencies: + eslint-visitor-keys "^2.0.0" + +eslint-visitor-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" + integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== + +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +eslint@8.34.0: + version "8.34.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.34.0.tgz#fe0ab0ef478104c1f9ebc5537e303d25a8fb22d6" + integrity sha512-1Z8iFsucw+7kSqXNZVslXS8Ioa4u2KM7GPwuKtkTFAqZ/cHMcEaR+1+Br0wLlot49cNxIiZk5wp8EAbPcYZxTg== + dependencies: + "@eslint/eslintrc" "^1.4.1" + "@humanwhocodes/config-array" "^0.11.8" + "@humanwhocodes/module-importer" "^1.0.1" + "@nodelib/fs.walk" "^1.2.8" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + doctrine "^3.0.0" + escape-string-regexp "^4.0.0" + eslint-scope "^7.1.1" + eslint-utils "^3.0.0" + eslint-visitor-keys "^3.3.0" + espree "^9.4.0" + esquery "^1.4.0" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + find-up "^5.0.0" + glob-parent "^6.0.2" + globals "^13.19.0" + grapheme-splitter "^1.0.4" + ignore "^5.2.0" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + is-path-inside "^3.0.3" + js-sdsl "^4.1.4" + js-yaml "^4.1.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.1" + regexpp "^3.2.0" + strip-ansi "^6.0.1" + strip-json-comments "^3.1.0" + text-table "^0.2.0" + +espree@^9.4.0: + version "9.6.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== + dependencies: + acorn "^8.9.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" + +esquery@^1.4.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" + integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +ethereum-cryptography@0.1.3, ethereum-cryptography@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz#8d6143cfc3d74bf79bbd8edecdf29e4ae20dd191" + integrity sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ== + dependencies: + "@types/pbkdf2" "^3.0.0" + "@types/secp256k1" "^4.0.1" + blakejs "^1.1.0" + browserify-aes "^1.2.0" + bs58check "^2.1.2" + create-hash "^1.2.0" + create-hmac "^1.1.7" + hash.js "^1.1.7" + keccak "^3.0.0" + pbkdf2 "^3.0.17" + randombytes "^2.1.0" + safe-buffer "^5.1.2" + scrypt-js "^3.0.0" + secp256k1 "^4.0.1" + setimmediate "^1.0.5" + +ethereum-cryptography@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz#5ccfa183e85fdaf9f9b299a79430c044268c9b3a" + integrity sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw== + dependencies: + "@noble/hashes" "1.2.0" + "@noble/secp256k1" "1.7.1" + "@scure/bip32" "1.1.5" + "@scure/bip39" "1.1.1" + +ethereumjs-abi@^0.6.8: + version "0.6.8" + resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz#71bc152db099f70e62f108b7cdfca1b362c6fcae" + integrity sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA== + dependencies: + bn.js "^4.11.8" + ethereumjs-util "^6.0.0" + +ethereumjs-util@^6.0.0, ethereumjs-util@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz#fcb4e4dd5ceacb9d2305426ab1a5cd93e3163b69" + integrity sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw== + dependencies: + "@types/bn.js" "^4.11.3" + bn.js "^4.11.0" + create-hash "^1.1.2" + elliptic "^6.5.2" + ethereum-cryptography "^0.1.3" + ethjs-util "0.1.6" + rlp "^2.2.3" + +ethjs-util@0.1.6, ethjs-util@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" + integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== + dependencies: + is-hex-prefixed "1.0.0" + strip-hex-prefix "1.0.0" + +evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-diff@^1.1.2, fast-diff@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" + integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== + +fast-glob@^3.2.9: + version "3.3.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" + integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fast-uri@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.3.tgz#892a1c91802d5d7860de728f18608a0573142241" + integrity sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw== + +fastq@^1.6.0: + version "1.17.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" + integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== + dependencies: + reusify "^1.0.4" + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== + dependencies: + locate-path "^2.0.0" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat-cache@^3.0.4: + version "3.2.0" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" + integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== + dependencies: + flatted "^3.2.9" + keyv "^4.5.3" + rimraf "^3.0.2" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +flatted@^3.2.9: + version "3.3.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" + integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== + +follow-redirects@^1.12.1: + version "1.15.9" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" + integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== + +form-data-encoder@^2.1.2: + version "2.1.4" + resolved "https://registry.yarnpkg.com/form-data-encoder/-/form-data-encoder-2.1.4.tgz#261ea35d2a70d48d30ec7a9603130fa5515e9cd5" + integrity sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw== + +fp-ts@1.19.3: + version "1.19.3" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.3.tgz#261a60d1088fbff01f91256f91d21d0caaaaa96f" + integrity sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg== + +fp-ts@^1.0.0: + version "1.19.5" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.5.tgz#3da865e585dfa1fdfd51785417357ac50afc520a" + integrity sha512-wDNqTimnzs8QqpldiId9OavWK2NptormjXnRJTQecNjzwfyp6P/8s/zG8e4h3ja3oqkKaY72UlTjQYt/1yXf9A== + +fs-extra@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +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== + +get-stream@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +glob-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob@7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.1.3: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^8.0.3, glob@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" + integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^5.0.1" + once "^1.3.0" + +globals@^13.19.0: + version "13.24.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" + integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== + dependencies: + type-fest "^0.20.2" + +globby@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + +got@^12.1.0: + version "12.6.1" + resolved "https://registry.yarnpkg.com/got/-/got-12.6.1.tgz#8869560d1383353204b5a9435f782df9c091f549" + integrity sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ== + dependencies: + "@sindresorhus/is" "^5.2.0" + "@szmarczak/http-timer" "^5.0.1" + cacheable-lookup "^7.0.0" + cacheable-request "^10.2.8" + decompress-response "^6.0.0" + form-data-encoder "^2.1.2" + get-stream "^6.0.1" + http2-wrapper "^2.1.10" + lowercase-keys "^3.0.0" + p-cancelable "^3.0.0" + responselike "^3.0.0" + +graceful-fs@4.2.10: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + +graceful-fs@^4.1.2, graceful-fs@^4.1.6: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +grapheme-splitter@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" + integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== + +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + +hardhat-abi-exporter@^2.10.1: + version "2.10.1" + resolved "https://registry.yarnpkg.com/hardhat-abi-exporter/-/hardhat-abi-exporter-2.10.1.tgz#b14884e233c73fe3f43360f014ad7fd6df4b6d25" + integrity sha512-X8GRxUTtebMAd2k4fcPyVnCdPa6dYK4lBsrwzKP5yiSq4i+WadWPIumaLfce53TUf/o2TnLpLOduyO1ylE2NHQ== + dependencies: + "@ethersproject/abi" "^5.5.0" + delete-empty "^3.0.0" + +hardhat@^2.22.2: + version "2.22.14" + resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.22.14.tgz#389bb3789a52adc0b1a3b4bfc9b891239d5a2b42" + integrity sha512-sD8vHtS9l5QQVHzyPPe3auwZDJyZ0fG3Z9YENVa4oOqVEefCuHcPzdU736rei3zUKTqkX0zPIHkSMHpu02Fq1A== + dependencies: + "@ethersproject/abi" "^5.1.2" + "@metamask/eth-sig-util" "^4.0.0" + "@nomicfoundation/edr" "^0.6.4" + "@nomicfoundation/ethereumjs-common" "4.0.4" + "@nomicfoundation/ethereumjs-tx" "5.0.4" + "@nomicfoundation/ethereumjs-util" "9.0.4" + "@nomicfoundation/solidity-analyzer" "^0.1.0" + "@sentry/node" "^5.18.1" + "@types/bn.js" "^5.1.0" + "@types/lru-cache" "^5.1.0" + adm-zip "^0.4.16" + aggregate-error "^3.0.0" + ansi-escapes "^4.3.0" + boxen "^5.1.2" + chalk "^2.4.2" + chokidar "^4.0.0" + ci-info "^2.0.0" + debug "^4.1.1" + enquirer "^2.3.0" + env-paths "^2.2.0" + ethereum-cryptography "^1.0.3" + ethereumjs-abi "^0.6.8" + find-up "^2.1.0" + fp-ts "1.19.3" + fs-extra "^7.0.1" + glob "7.2.0" + immutable "^4.0.0-rc.12" + io-ts "1.10.4" + json-stream-stringify "^3.1.4" + keccak "^3.0.2" + lodash "^4.17.11" + mnemonist "^0.38.0" + mocha "^10.0.0" + p-map "^4.0.0" + raw-body "^2.4.1" + resolve "1.17.0" + semver "^6.3.0" + solc "0.8.26" + source-map-support "^0.5.13" + stacktrace-parser "^0.1.10" + tsort "0.0.1" + undici "^5.14.0" + uuid "^8.3.2" + ws "^7.4.6" + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +hash-base@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== + dependencies: + inherits "^2.0.4" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +he@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +http-cache-semantics@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" + integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +http2-wrapper@^2.1.10: + version "2.2.1" + resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-2.2.1.tgz#310968153dcdedb160d8b72114363ef5fce1f64a" + integrity sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ== + dependencies: + quick-lru "^5.1.1" + resolve-alpn "^1.2.0" + +https-proxy-agent@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ignore@^5.2.0, ignore@^5.2.4: + version "5.3.2" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" + integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== + +immutable@^4.0.0-rc.12: + version "4.3.7" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.7.tgz#c70145fc90d89fb02021e65c84eb0226e4e5a381" + integrity sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw== + +import-fresh@^3.0.0, import-fresh@^3.2.1, import-fresh@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +ini@^1.3.4, ini@~1.3.0: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + +io-ts@1.10.4: + version "1.10.4" + resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-1.10.4.tgz#cd5401b138de88e4f920adbcb7026e2d1967e6e2" + integrity sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g== + dependencies: + fp-ts "^1.0.0" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +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== + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-hex-prefixed@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" + integrity sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA== + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-path-inside@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +js-sdsl@^4.1.4: + version "4.4.2" + resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.4.2.tgz#2e3c031b1f47d3aca8b775532e3ebb0818e7f847" + integrity sha512-dwXFwByc/ajSV6m5bcKAPwe4yDDF6D614pxmIi5odytzxRlwqF6nwoiCek80Ixc7Cvma5awClxrzFtxCQvcM8w== + +js-sha3@0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + +json-stream-stringify@^3.1.4: + version "3.1.6" + resolved "https://registry.yarnpkg.com/json-stream-stringify/-/json-stream-stringify-3.1.6.tgz#ebe32193876fb99d4ec9f612389a8d8e2b5d54d4" + integrity sha512-x7fpwxOkbhFCaJDJ8vb1fBY3DdSa4AlITaz+HHILQJzdPMnHEFjxPwVUi1ALIbcIxDE0PNe/0i7frnY8QnBQog== + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== + optionalDependencies: + graceful-fs "^4.1.6" + +keccak@^3.0.0, keccak@^3.0.2: + version "3.0.4" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.4.tgz#edc09b89e633c0549da444432ecf062ffadee86d" + integrity sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q== + dependencies: + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + readable-stream "^3.6.0" + +keyv@^4.5.3: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + dependencies: + json-buffer "3.0.1" + +latest-version@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-7.0.0.tgz#843201591ea81a4d404932eeb61240fe04e9e5da" + integrity sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg== + dependencies: + package-json "^8.1.0" + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA== + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.isequal@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash.truncate@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" + integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== + +lodash@^4.17.11, lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +log-symbols@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +lowercase-keys@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-3.0.0.tgz#c5e7d442e37ead247ae9db117a9d0a467c89d4f2" + integrity sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ== + +lru_map@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" + integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== + +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== + +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +memorystream@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" + integrity sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw== + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.4: + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== + dependencies: + braces "^3.0.3" + picomatch "^2.3.1" + +mimic-response@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" + integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== + +mimic-response@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-4.0.0.tgz#35468b19e7c75d10f5165ea25e75a5ceea7cf70f" + integrity sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg== + +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" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== + +minimatch@9.0.3: + version "9.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^5.0.1, minimatch@^5.1.6: + version "5.1.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + +minimist@^1.2.0: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +mnemonist@^0.38.0: + version "0.38.5" + resolved "https://registry.yarnpkg.com/mnemonist/-/mnemonist-0.38.5.tgz#4adc7f4200491237fe0fa689ac0b86539685cade" + integrity sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg== + dependencies: + obliterator "^2.0.0" + +mocha@^10.0.0: + version "10.7.3" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.7.3.tgz#ae32003cabbd52b59aece17846056a68eb4b0752" + integrity sha512-uQWxAu44wwiACGqjbPYmjo7Lg8sFrS3dQe7PP2FQI+woptP4vZXSMcfMyFL/e1yFEeEpV4RtyTpZROOKmxis+A== + dependencies: + ansi-colors "^4.1.3" + browser-stdout "^1.3.1" + chokidar "^3.5.3" + debug "^4.3.5" + diff "^5.2.0" + escape-string-regexp "^4.0.0" + find-up "^5.0.0" + glob "^8.1.0" + he "^1.2.0" + js-yaml "^4.1.0" + log-symbols "^4.1.0" + minimatch "^5.1.6" + ms "^2.1.3" + serialize-javascript "^6.0.2" + strip-json-comments "^3.1.1" + supports-color "^8.1.1" + workerpool "^6.5.1" + yargs "^16.2.0" + yargs-parser "^20.2.9" + yargs-unparser "^2.0.0" + +ms@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +node-addon-api@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" + integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== + +node-addon-api@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.1.0.tgz#49da1ca055e109a23d537e9de43c09cca21eb762" + integrity sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA== + +node-gyp-build@^4.2.0: + version "4.8.2" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.2.tgz#4f802b71c1ab2ca16af830e6c1ea7dd1ad9496fa" + integrity sha512-IRUxE4BVsHWXkV/SFOut4qTlagw2aM8T5/vnTsmrHJvVoKueJHRc/JaFND7QDDc61kLYUJ6qlZM3sqTSyx2dTw== + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +normalize-url@^8.0.0: + version "8.0.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-8.0.1.tgz#9b7d96af9836577c58f5883e939365fa15623a4a" + integrity sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w== + +obliterator@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-2.0.4.tgz#fa650e019b2d075d745e44f1effeb13a2adbe816" + integrity sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ== + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +optionator@^0.9.1: + version "0.9.4" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" + integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.5" + +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== + +p-cancelable@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-3.0.0.tgz#63826694b54d61ca1c20ebcb6d3ecf5e14cd8050" + integrity sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw== + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg== + dependencies: + p-limit "^1.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww== + +package-json@^8.1.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/package-json/-/package-json-8.1.1.tgz#3e9948e43df40d1e8e78a85485f1070bf8f03dc8" + integrity sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA== + dependencies: + got "^12.1.0" + registry-auth-token "^5.0.1" + registry-url "^6.0.0" + semver "^7.3.7" + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-json@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-starts-with@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-starts-with/-/path-starts-with-2.0.1.tgz#cd8b6213c141a9f2dd86c748310acdfa6493abb1" + integrity sha512-wZ3AeiRBRlNwkdUxvBANh0+esnt38DLffHDujZyRHkqkaKHTglnY2EP5UX3b8rdeiSutgO4y9NEJwXezNP5vHg== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +pbkdf2@^3.0.17: + version "3.1.2" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" + integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +picocolors@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pluralize@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" + integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA== + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + +prettier-plugin-organize-imports@3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-3.2.4.tgz#77967f69d335e9c8e6e5d224074609309c62845e" + integrity sha512-6m8WBhIp0dfwu0SkgfOxJqh+HpdyfqSSLfKKRZSFbDuEQXDDndb8fTpRWkUrX/uBenkex3MgnVk0J3b3Y5byog== + +prettier-plugin-solidity@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prettier-plugin-solidity/-/prettier-plugin-solidity-1.1.2.tgz#452be4df925a4b16a974a04235839c9f56c2d10d" + integrity sha512-KC5oNbFJfyBaFiO0kl56J6AXnDmr9tUlBV1iqo864x4KQrKYKaBZvW9jhT2oC0NHoNp7/GoMJNxqL8pp8k7C/g== + dependencies: + "@solidity-parser/parser" "^0.15.0" + semver "^7.3.8" + solidity-comments-extractor "^0.0.7" + +prettier@2.8.4: + version "2.8.4" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.4.tgz#34dd2595629bfbb79d344ac4a91ff948694463c3" + integrity sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw== + +prettier@^2.8.3: + version "2.8.8" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" + integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== + +proto-list@~1.2.1: + version "1.2.4" + resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" + integrity sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA== + +punycode@^2.1.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +quick-lru@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" + integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +raw-body@^2.4.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" + integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + +rc@1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +readable-stream@^3.6.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readdirp@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.0.2.tgz#388fccb8b75665da3abffe2d8f8ed59fe74c230a" + integrity sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA== + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +regexpp@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" + integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== + +registry-auth-token@^5.0.1: + version "5.0.2" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-5.0.2.tgz#8b026cc507c8552ebbe06724136267e63302f756" + integrity sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ== + dependencies: + "@pnpm/npm-conf" "^2.1.0" + +registry-url@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-6.0.1.tgz#056d9343680f2f64400032b1e199faa692286c58" + integrity sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q== + dependencies: + rc "1.2.8" + +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== + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +resolve-alpn@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" + integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g== + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve@1.17.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + dependencies: + path-parse "^1.0.6" + +responselike@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-3.0.0.tgz#20decb6c298aff0dbee1c355ca95461d42823626" + integrity sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg== + dependencies: + lowercase-keys "^3.0.0" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@^2.6.2: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +rlp@^2.2.3: + version "2.2.7" + resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf" + integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ== + dependencies: + bn.js "^5.2.0" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +scrypt-js@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" + integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== + +secp256k1@^4.0.1: + version "4.0.4" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.4.tgz#58f0bfe1830fe777d9ca1ffc7574962a8189f8ab" + integrity sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw== + dependencies: + elliptic "^6.5.7" + node-addon-api "^5.0.0" + node-gyp-build "^4.2.0" + +semver@^5.5.0: + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + +semver@^6.3.0: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.3.7, semver@^7.3.8, semver@^7.5.2, semver@^7.5.4: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== + +serialize-javascript@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" + integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== + dependencies: + randombytes "^2.1.0" + +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +solc@0.8.26: + version "0.8.26" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.8.26.tgz#afc78078953f6ab3e727c338a2fefcd80dd5b01a" + integrity sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g== + dependencies: + command-exists "^1.2.8" + commander "^8.1.0" + follow-redirects "^1.12.1" + js-sha3 "0.8.0" + memorystream "^0.3.1" + semver "^5.5.0" + tmp "0.0.33" + +solhint-plugin-prettier@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/solhint-plugin-prettier/-/solhint-plugin-prettier-0.0.5.tgz#e3b22800ba435cd640a9eca805a7f8bc3e3e6a6b" + integrity sha512-7jmWcnVshIrO2FFinIvDQmhQpfpS2rRRn3RejiYgnjIE68xO2bvrYvjqVNfrio4xH9ghOqn83tKuTzLjEbmGIA== + dependencies: + prettier-linter-helpers "^1.0.0" + +solhint@^4.5.4: + version "4.5.4" + resolved "https://registry.yarnpkg.com/solhint/-/solhint-4.5.4.tgz#171cf33f46c36b8499efe60c0e425f6883a54e50" + integrity sha512-Cu1XiJXub2q1eCr9kkJ9VPv1sGcmj3V7Zb76B0CoezDOB9bu3DxKIFFH7ggCl9fWpEPD6xBmRLfZrYijkVmujQ== + dependencies: + "@solidity-parser/parser" "^0.18.0" + ajv "^6.12.6" + antlr4 "^4.13.1-patch-1" + ast-parents "^0.0.1" + chalk "^4.1.2" + commander "^10.0.0" + cosmiconfig "^8.0.0" + fast-diff "^1.2.0" + glob "^8.0.3" + ignore "^5.2.4" + js-yaml "^4.1.0" + latest-version "^7.0.0" + lodash "^4.17.21" + pluralize "^8.0.0" + semver "^7.5.2" + strip-ansi "^6.0.1" + table "^6.8.1" + text-table "^0.2.0" + optionalDependencies: + prettier "^2.8.3" + +solidity-comments-extractor@^0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz#99d8f1361438f84019795d928b931f4e5c39ca19" + integrity sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw== + +source-map-support@^0.5.13: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +stacktrace-parser@^0.1.10: + version "0.1.10" + resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a" + integrity sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg== + dependencies: + type-fest "^0.7.1" + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, 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" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +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" + +strip-hex-prefix@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" + integrity sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A== + dependencies: + is-hex-prefixed "1.0.0" + +strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-color@^8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +table@^6.8.1: + version "6.8.2" + resolved "https://registry.yarnpkg.com/table/-/table-6.8.2.tgz#c5504ccf201213fa227248bdc8c5569716ac6c58" + integrity sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA== + dependencies: + ajv "^8.0.1" + lodash.truncate "^4.4.2" + slice-ansi "^4.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + +tmp@0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +ts-api-utils@^1.0.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" + integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== + +ts-node@^10.9.2: + version "10.9.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" + integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== + 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" + +tslib@^1.9.3: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tsort@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/tsort/-/tsort-0.0.1.tgz#e2280f5e817f8bf4275657fd0f9aebd44f5a2786" + integrity sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw== + +tweetnacl-util@^0.15.1: + version "0.15.1" + resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b" + integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw== + +tweetnacl@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" + integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +type-fest@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" + integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== + +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== + +undici-types@~6.19.2: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== + +undici@^5.14.0: + version "5.28.4" + resolved "https://registry.yarnpkg.com/undici/-/undici-5.28.4.tgz#6b280408edb6a1a604a9b20340f45b422e373068" + integrity sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g== + dependencies: + "@fastify/busboy" "^2.0.0" + +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + +unpipe@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +util-deprecate@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +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== + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +widest-line@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" + integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== + dependencies: + string-width "^4.0.0" + +word-wrap@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== + +workerpool@^6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.5.1.tgz#060f73b39d0caf97c6db64da004cd01b4c099544" + integrity sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA== + +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" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +ws@^7.4.6: + version "7.5.10" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" + integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== + +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== + +yargs-parser@^20.2.2, yargs-parser@^20.2.9: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-unparser@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@^16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/precompiles/staking/IStaking.abi b/precompiles/staking/IStaking.abi new file mode 100644 index 00000000..9fc0e395 --- /dev/null +++ b/precompiles/staking/IStaking.abi @@ -0,0 +1,1716 @@ +[ + { + "inputs": [ + { + "internalType": "string", + "name": "validatorSrcAddress", + "type": "string" + }, + { + "internalType": "string", + "name": "validatorDstAddress", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "beginRedelegate", + "outputs": [ + { + "internalType": "uint256", + "name": "completionTime", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "validatorAddress", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "creationHeight", + "type": "uint256" + } + ], + "name": "cancelUnbondingDelegation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "moniker", + "type": "string" + }, + { + "internalType": "string", + "name": "identity", + "type": "string" + }, + { + "internalType": "string", + "name": "website", + "type": "string" + }, + { + "internalType": "string", + "name": "securityContact", + "type": "string" + }, + { + "internalType": "string", + "name": "details", + "type": "string" + } + ], + "internalType": "struct Description", + "name": "description", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "rate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxChangeRate", + "type": "uint256" + } + ], + "internalType": "struct CommissionRates", + "name": "commission", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "minSelfDelegation", + "type": "uint256" + }, + { + "internalType": "string", + "name": "pubkey", + "type": "string" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "createValidator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "validatorAddress", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "delegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "delegatorAddr", + "type": "string" + }, + { + "internalType": "string", + "name": "validatorAddr", + "type": "string" + } + ], + "name": "delegation", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "delegatorAddress", + "type": "string" + }, + { + "internalType": "string", + "name": "validatorAddress", + "type": "string" + }, + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "internalType": "struct Delegation", + "name": "delegation", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "delegatorAddr", + "type": "string" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offset", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "limit", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "countTotal", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reverse", + "type": "bool" + } + ], + "internalType": "struct PageRequest", + "name": "pagination", + "type": "tuple" + } + ], + "name": "delegatorDelegations", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "string", + "name": "delegatorAddress", + "type": "string" + }, + { + "internalType": "string", + "name": "validatorAddress", + "type": "string" + }, + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "internalType": "struct Delegation", + "name": "delegation", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "internalType": "struct DelegationResponse[]", + "name": "delegationResponses", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "nextKey", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "total", + "type": "uint64" + } + ], + "internalType": "struct PageResponse", + "name": "paginationResult", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "delegatorAddr", + "type": "string" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offset", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "limit", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "countTotal", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reverse", + "type": "bool" + } + ], + "internalType": "struct PageRequest", + "name": "pagination", + "type": "tuple" + } + ], + "name": "delegatorUnbondingDelegations", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "delegatorAddress", + "type": "string" + }, + { + "internalType": "string", + "name": "validatorAddress", + "type": "string" + }, + { + "components": [ + { + "internalType": "int64", + "name": "creationHeight", + "type": "int64" + }, + { + "internalType": "int64", + "name": "completionTime", + "type": "int64" + }, + { + "internalType": "uint256", + "name": "initialBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "unbondingId", + "type": "uint64" + }, + { + "internalType": "int64", + "name": "unbondingOnHoldRefCount", + "type": "int64" + } + ], + "internalType": "struct UnbondingDelegationEntry[]", + "name": "entries", + "type": "tuple[]" + } + ], + "internalType": "struct UnbondingDelegation[]", + "name": "unbondingResponses", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "nextKey", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "total", + "type": "uint64" + } + ], + "internalType": "struct PageResponse", + "name": "paginationResult", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "delegatorAddr", + "type": "string" + }, + { + "internalType": "string", + "name": "validatorAddr", + "type": "string" + } + ], + "name": "delegatorValidator", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "operatorAddress", + "type": "string" + }, + { + "internalType": "string", + "name": "consensusPubkey", + "type": "string" + }, + { + "internalType": "bool", + "name": "jailed", + "type": "bool" + }, + { + "internalType": "enum BondStatus", + "name": "status", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "delegatorShares", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "string", + "name": "moniker", + "type": "string" + }, + { + "internalType": "string", + "name": "identity", + "type": "string" + }, + { + "internalType": "string", + "name": "website", + "type": "string" + }, + { + "internalType": "string", + "name": "securityContact", + "type": "string" + }, + { + "internalType": "string", + "name": "details", + "type": "string" + } + ], + "internalType": "struct Description", + "name": "description", + "type": "tuple" + }, + { + "internalType": "int64", + "name": "unbondingHeight", + "type": "int64" + }, + { + "internalType": "int64", + "name": "unbondingTime", + "type": "int64" + }, + { + "components": [ + { + "components": [ + { + "internalType": "uint256", + "name": "rate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxChangeRate", + "type": "uint256" + } + ], + "internalType": "struct CommissionRates", + "name": "commissionRates", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "updateTime", + "type": "uint256" + } + ], + "internalType": "struct Commission", + "name": "commission", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "minSelfDelegation", + "type": "uint256" + }, + { + "internalType": "int64", + "name": "unbondingOnHoldRefCount", + "type": "int64" + }, + { + "internalType": "uint64[]", + "name": "unbondingIds", + "type": "uint64[]" + } + ], + "internalType": "struct Validator", + "name": "validator", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "delegatorAddr", + "type": "string" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offset", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "limit", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "countTotal", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reverse", + "type": "bool" + } + ], + "internalType": "struct PageRequest", + "name": "pagination", + "type": "tuple" + } + ], + "name": "delegatorValidators", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "operatorAddress", + "type": "string" + }, + { + "internalType": "string", + "name": "consensusPubkey", + "type": "string" + }, + { + "internalType": "bool", + "name": "jailed", + "type": "bool" + }, + { + "internalType": "enum BondStatus", + "name": "status", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "delegatorShares", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "string", + "name": "moniker", + "type": "string" + }, + { + "internalType": "string", + "name": "identity", + "type": "string" + }, + { + "internalType": "string", + "name": "website", + "type": "string" + }, + { + "internalType": "string", + "name": "securityContact", + "type": "string" + }, + { + "internalType": "string", + "name": "details", + "type": "string" + } + ], + "internalType": "struct Description", + "name": "description", + "type": "tuple" + }, + { + "internalType": "int64", + "name": "unbondingHeight", + "type": "int64" + }, + { + "internalType": "int64", + "name": "unbondingTime", + "type": "int64" + }, + { + "components": [ + { + "components": [ + { + "internalType": "uint256", + "name": "rate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxChangeRate", + "type": "uint256" + } + ], + "internalType": "struct CommissionRates", + "name": "commissionRates", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "updateTime", + "type": "uint256" + } + ], + "internalType": "struct Commission", + "name": "commission", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "minSelfDelegation", + "type": "uint256" + }, + { + "internalType": "int64", + "name": "unbondingOnHoldRefCount", + "type": "int64" + }, + { + "internalType": "uint64[]", + "name": "unbondingIds", + "type": "uint64[]" + } + ], + "internalType": "struct Validator[]", + "name": "validators", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "nextKey", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "total", + "type": "uint64" + } + ], + "internalType": "struct PageResponse", + "name": "paginationResult", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "moniker", + "type": "string" + }, + { + "internalType": "string", + "name": "identity", + "type": "string" + }, + { + "internalType": "string", + "name": "website", + "type": "string" + }, + { + "internalType": "string", + "name": "securityContact", + "type": "string" + }, + { + "internalType": "string", + "name": "details", + "type": "string" + } + ], + "internalType": "struct Description", + "name": "description", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "bool", + "name": "isNull", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "internalType": "struct NullableUint", + "name": "commissionRate", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "bool", + "name": "isNull", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "internalType": "struct NullableUint", + "name": "minSelfDelegation", + "type": "tuple" + } + ], + "name": "editValidator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "params", + "outputs": [ + { + "components": [ + { + "internalType": "int64", + "name": "unbondingTime", + "type": "int64" + }, + { + "internalType": "uint32", + "name": "maxValidators", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxEntries", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "historicalEntries", + "type": "uint32" + }, + { + "internalType": "string", + "name": "bondDenom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "minCommissionRate", + "type": "uint256" + } + ], + "internalType": "struct Params", + "name": "params", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pool", + "outputs": [ + { + "internalType": "uint256", + "name": "notBondedTokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "bondedTokens", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "delegatorAddress", + "type": "string" + }, + { + "internalType": "string", + "name": "srcValidatorAddress", + "type": "string" + }, + { + "internalType": "string", + "name": "dstValidatorAddress", + "type": "string" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offset", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "limit", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "countTotal", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reverse", + "type": "bool" + } + ], + "internalType": "struct PageRequest", + "name": "pageRequest", + "type": "tuple" + } + ], + "name": "redelegations", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "string", + "name": "delegatorAddress", + "type": "string" + }, + { + "internalType": "string", + "name": "validatorSrcAddress", + "type": "string" + }, + { + "internalType": "string", + "name": "validatorDstAddress", + "type": "string" + }, + { + "components": [ + { + "internalType": "int64", + "name": "creationHeight", + "type": "int64" + }, + { + "internalType": "int64", + "name": "completionTime", + "type": "int64" + }, + { + "internalType": "uint256", + "name": "initialBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sharesDst", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "unbondingId", + "type": "uint64" + }, + { + "internalType": "int64", + "name": "unbondingOnHoldRefCount", + "type": "int64" + } + ], + "internalType": "struct RedelegationEntry[]", + "name": "entries", + "type": "tuple[]" + } + ], + "internalType": "struct Redelegation", + "name": "redelegation", + "type": "tuple" + }, + { + "components": [ + { + "components": [ + { + "internalType": "int64", + "name": "creationHeight", + "type": "int64" + }, + { + "internalType": "int64", + "name": "completionTime", + "type": "int64" + }, + { + "internalType": "uint256", + "name": "initialBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sharesDst", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "unbondingId", + "type": "uint64" + }, + { + "internalType": "int64", + "name": "unbondingOnHoldRefCount", + "type": "int64" + } + ], + "internalType": "struct RedelegationEntry", + "name": "redelegationEntry", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "internalType": "struct RedelegationEntryResponse[]", + "name": "entries", + "type": "tuple[]" + } + ], + "internalType": "struct RedelegationResponse[]", + "name": "redelegationResponses", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "nextKey", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "total", + "type": "uint64" + } + ], + "internalType": "struct PageResponse", + "name": "paginationResult", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "delegatorAddr", + "type": "string" + }, + { + "internalType": "string", + "name": "validatorAddr", + "type": "string" + } + ], + "name": "unbondingDelegation", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "delegatorAddress", + "type": "string" + }, + { + "internalType": "string", + "name": "validatorAddress", + "type": "string" + }, + { + "components": [ + { + "internalType": "int64", + "name": "creationHeight", + "type": "int64" + }, + { + "internalType": "int64", + "name": "completionTime", + "type": "int64" + }, + { + "internalType": "uint256", + "name": "initialBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "unbondingId", + "type": "uint64" + }, + { + "internalType": "int64", + "name": "unbondingOnHoldRefCount", + "type": "int64" + } + ], + "internalType": "struct UnbondingDelegationEntry[]", + "name": "entries", + "type": "tuple[]" + } + ], + "internalType": "struct UnbondingDelegation", + "name": "unbond", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "validatorAddress", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "undelegate", + "outputs": [ + { + "internalType": "uint256", + "name": "completionTime", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "validatorAddress", + "type": "string" + } + ], + "name": "validator", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "operatorAddress", + "type": "string" + }, + { + "internalType": "string", + "name": "consensusPubkey", + "type": "string" + }, + { + "internalType": "bool", + "name": "jailed", + "type": "bool" + }, + { + "internalType": "enum BondStatus", + "name": "status", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "delegatorShares", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "string", + "name": "moniker", + "type": "string" + }, + { + "internalType": "string", + "name": "identity", + "type": "string" + }, + { + "internalType": "string", + "name": "website", + "type": "string" + }, + { + "internalType": "string", + "name": "securityContact", + "type": "string" + }, + { + "internalType": "string", + "name": "details", + "type": "string" + } + ], + "internalType": "struct Description", + "name": "description", + "type": "tuple" + }, + { + "internalType": "int64", + "name": "unbondingHeight", + "type": "int64" + }, + { + "internalType": "int64", + "name": "unbondingTime", + "type": "int64" + }, + { + "components": [ + { + "components": [ + { + "internalType": "uint256", + "name": "rate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxChangeRate", + "type": "uint256" + } + ], + "internalType": "struct CommissionRates", + "name": "commissionRates", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "updateTime", + "type": "uint256" + } + ], + "internalType": "struct Commission", + "name": "commission", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "minSelfDelegation", + "type": "uint256" + }, + { + "internalType": "int64", + "name": "unbondingOnHoldRefCount", + "type": "int64" + }, + { + "internalType": "uint64[]", + "name": "unbondingIds", + "type": "uint64[]" + } + ], + "internalType": "struct Validator", + "name": "validator", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "validatorAddr", + "type": "string" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offset", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "limit", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "countTotal", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reverse", + "type": "bool" + } + ], + "internalType": "struct PageRequest", + "name": "pagination", + "type": "tuple" + } + ], + "name": "validatorDelegations", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "string", + "name": "delegatorAddress", + "type": "string" + }, + { + "internalType": "string", + "name": "validatorAddress", + "type": "string" + }, + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "internalType": "struct Delegation", + "name": "delegation", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "internalType": "struct DelegationResponse[]", + "name": "delegationResponses", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "nextKey", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "total", + "type": "uint64" + } + ], + "internalType": "struct PageResponse", + "name": "paginationResult", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "validatorAddr", + "type": "string" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offset", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "limit", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "countTotal", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reverse", + "type": "bool" + } + ], + "internalType": "struct PageRequest", + "name": "pagination", + "type": "tuple" + } + ], + "name": "validatorUnbondingDelegations", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "delegatorAddress", + "type": "string" + }, + { + "internalType": "string", + "name": "validatorAddress", + "type": "string" + }, + { + "components": [ + { + "internalType": "int64", + "name": "creationHeight", + "type": "int64" + }, + { + "internalType": "int64", + "name": "completionTime", + "type": "int64" + }, + { + "internalType": "uint256", + "name": "initialBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "unbondingId", + "type": "uint64" + }, + { + "internalType": "int64", + "name": "unbondingOnHoldRefCount", + "type": "int64" + } + ], + "internalType": "struct UnbondingDelegationEntry[]", + "name": "entries", + "type": "tuple[]" + } + ], + "internalType": "struct UnbondingDelegation[]", + "name": "unbondingResponses", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "nextKey", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "total", + "type": "uint64" + } + ], + "internalType": "struct PageResponse", + "name": "paginationResult", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "status", + "type": "string" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offset", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "limit", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "countTotal", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reverse", + "type": "bool" + } + ], + "internalType": "struct PageRequest", + "name": "pagination", + "type": "tuple" + } + ], + "name": "validators", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "operatorAddress", + "type": "string" + }, + { + "internalType": "string", + "name": "consensusPubkey", + "type": "string" + }, + { + "internalType": "bool", + "name": "jailed", + "type": "bool" + }, + { + "internalType": "enum BondStatus", + "name": "status", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "delegatorShares", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "string", + "name": "moniker", + "type": "string" + }, + { + "internalType": "string", + "name": "identity", + "type": "string" + }, + { + "internalType": "string", + "name": "website", + "type": "string" + }, + { + "internalType": "string", + "name": "securityContact", + "type": "string" + }, + { + "internalType": "string", + "name": "details", + "type": "string" + } + ], + "internalType": "struct Description", + "name": "description", + "type": "tuple" + }, + { + "internalType": "int64", + "name": "unbondingHeight", + "type": "int64" + }, + { + "internalType": "int64", + "name": "unbondingTime", + "type": "int64" + }, + { + "components": [ + { + "components": [ + { + "internalType": "uint256", + "name": "rate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxChangeRate", + "type": "uint256" + } + ], + "internalType": "struct CommissionRates", + "name": "commissionRates", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "updateTime", + "type": "uint256" + } + ], + "internalType": "struct Commission", + "name": "commission", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "minSelfDelegation", + "type": "uint256" + }, + { + "internalType": "int64", + "name": "unbondingOnHoldRefCount", + "type": "int64" + }, + { + "internalType": "uint64[]", + "name": "unbondingIds", + "type": "uint64[]" + } + ], + "internalType": "struct Validator[]", + "name": "validators", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "nextKey", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "total", + "type": "uint64" + } + ], + "internalType": "struct PageResponse", + "name": "paginationResult", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/precompiles/staking/contract.go b/precompiles/staking/contract.go new file mode 100644 index 00000000..45a01831 --- /dev/null +++ b/precompiles/staking/contract.go @@ -0,0 +1,835 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package staking + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription +) + +// StakingMetaData contains all meta data concerning the Staking contract. +var StakingMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"validatorSrcAddress\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"validatorDstAddress\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"beginRedelegate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"completionTime\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"validatorAddress\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"creationHeight\",\"type\":\"uint256\"}],\"name\":\"cancelUnbondingDelegation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"moniker\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"identity\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"website\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"securityContact\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"details\",\"type\":\"string\"}],\"internalType\":\"structDescription\",\"name\":\"description\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"rate\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxRate\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxChangeRate\",\"type\":\"uint256\"}],\"internalType\":\"structCommissionRates\",\"name\":\"commission\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"minSelfDelegation\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"pubkey\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"createValidator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"validatorAddress\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"delegate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"delegatorAddr\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"validatorAddr\",\"type\":\"string\"}],\"name\":\"delegation\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"delegatorAddress\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"validatorAddress\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"shares\",\"type\":\"uint256\"}],\"internalType\":\"structDelegation\",\"name\":\"delegation\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"delegatorAddr\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"key\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offset\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"limit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"countTotal\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reverse\",\"type\":\"bool\"}],\"internalType\":\"structPageRequest\",\"name\":\"pagination\",\"type\":\"tuple\"}],\"name\":\"delegatorDelegations\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"delegatorAddress\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"validatorAddress\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"shares\",\"type\":\"uint256\"}],\"internalType\":\"structDelegation\",\"name\":\"delegation\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"internalType\":\"structDelegationResponse[]\",\"name\":\"delegationResponses\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"nextKey\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"total\",\"type\":\"uint64\"}],\"internalType\":\"structPageResponse\",\"name\":\"paginationResult\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"delegatorAddr\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"key\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offset\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"limit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"countTotal\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reverse\",\"type\":\"bool\"}],\"internalType\":\"structPageRequest\",\"name\":\"pagination\",\"type\":\"tuple\"}],\"name\":\"delegatorUnbondingDelegations\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"delegatorAddress\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"validatorAddress\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"creationHeight\",\"type\":\"int64\"},{\"internalType\":\"int64\",\"name\":\"completionTime\",\"type\":\"int64\"},{\"internalType\":\"uint256\",\"name\":\"initialBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"unbondingId\",\"type\":\"uint64\"},{\"internalType\":\"int64\",\"name\":\"unbondingOnHoldRefCount\",\"type\":\"int64\"}],\"internalType\":\"structUnbondingDelegationEntry[]\",\"name\":\"entries\",\"type\":\"tuple[]\"}],\"internalType\":\"structUnbondingDelegation[]\",\"name\":\"unbondingResponses\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"nextKey\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"total\",\"type\":\"uint64\"}],\"internalType\":\"structPageResponse\",\"name\":\"paginationResult\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"delegatorAddr\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"validatorAddr\",\"type\":\"string\"}],\"name\":\"delegatorValidator\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"operatorAddress\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"consensusPubkey\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"jailed\",\"type\":\"bool\"},{\"internalType\":\"enumBondStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"delegatorShares\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"moniker\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"identity\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"website\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"securityContact\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"details\",\"type\":\"string\"}],\"internalType\":\"structDescription\",\"name\":\"description\",\"type\":\"tuple\"},{\"internalType\":\"int64\",\"name\":\"unbondingHeight\",\"type\":\"int64\"},{\"internalType\":\"int64\",\"name\":\"unbondingTime\",\"type\":\"int64\"},{\"components\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"rate\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxRate\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxChangeRate\",\"type\":\"uint256\"}],\"internalType\":\"structCommissionRates\",\"name\":\"commissionRates\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"updateTime\",\"type\":\"uint256\"}],\"internalType\":\"structCommission\",\"name\":\"commission\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"minSelfDelegation\",\"type\":\"uint256\"},{\"internalType\":\"int64\",\"name\":\"unbondingOnHoldRefCount\",\"type\":\"int64\"},{\"internalType\":\"uint64[]\",\"name\":\"unbondingIds\",\"type\":\"uint64[]\"}],\"internalType\":\"structValidator\",\"name\":\"validator\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"delegatorAddr\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"key\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offset\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"limit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"countTotal\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reverse\",\"type\":\"bool\"}],\"internalType\":\"structPageRequest\",\"name\":\"pagination\",\"type\":\"tuple\"}],\"name\":\"delegatorValidators\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"operatorAddress\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"consensusPubkey\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"jailed\",\"type\":\"bool\"},{\"internalType\":\"enumBondStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"delegatorShares\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"moniker\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"identity\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"website\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"securityContact\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"details\",\"type\":\"string\"}],\"internalType\":\"structDescription\",\"name\":\"description\",\"type\":\"tuple\"},{\"internalType\":\"int64\",\"name\":\"unbondingHeight\",\"type\":\"int64\"},{\"internalType\":\"int64\",\"name\":\"unbondingTime\",\"type\":\"int64\"},{\"components\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"rate\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxRate\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxChangeRate\",\"type\":\"uint256\"}],\"internalType\":\"structCommissionRates\",\"name\":\"commissionRates\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"updateTime\",\"type\":\"uint256\"}],\"internalType\":\"structCommission\",\"name\":\"commission\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"minSelfDelegation\",\"type\":\"uint256\"},{\"internalType\":\"int64\",\"name\":\"unbondingOnHoldRefCount\",\"type\":\"int64\"},{\"internalType\":\"uint64[]\",\"name\":\"unbondingIds\",\"type\":\"uint64[]\"}],\"internalType\":\"structValidator[]\",\"name\":\"validators\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"nextKey\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"total\",\"type\":\"uint64\"}],\"internalType\":\"structPageResponse\",\"name\":\"paginationResult\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"moniker\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"identity\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"website\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"securityContact\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"details\",\"type\":\"string\"}],\"internalType\":\"structDescription\",\"name\":\"description\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isNull\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"internalType\":\"structNullableUint\",\"name\":\"commissionRate\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isNull\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"internalType\":\"structNullableUint\",\"name\":\"minSelfDelegation\",\"type\":\"tuple\"}],\"name\":\"editValidator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"params\",\"outputs\":[{\"components\":[{\"internalType\":\"int64\",\"name\":\"unbondingTime\",\"type\":\"int64\"},{\"internalType\":\"uint32\",\"name\":\"maxValidators\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxEntries\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"historicalEntries\",\"type\":\"uint32\"},{\"internalType\":\"string\",\"name\":\"bondDenom\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"minCommissionRate\",\"type\":\"uint256\"}],\"internalType\":\"structParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pool\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"notBondedTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"bondedTokens\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"delegatorAddress\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"srcValidatorAddress\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"dstValidatorAddress\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"key\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offset\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"limit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"countTotal\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reverse\",\"type\":\"bool\"}],\"internalType\":\"structPageRequest\",\"name\":\"pageRequest\",\"type\":\"tuple\"}],\"name\":\"redelegations\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"delegatorAddress\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"validatorSrcAddress\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"validatorDstAddress\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"creationHeight\",\"type\":\"int64\"},{\"internalType\":\"int64\",\"name\":\"completionTime\",\"type\":\"int64\"},{\"internalType\":\"uint256\",\"name\":\"initialBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"sharesDst\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"unbondingId\",\"type\":\"uint64\"},{\"internalType\":\"int64\",\"name\":\"unbondingOnHoldRefCount\",\"type\":\"int64\"}],\"internalType\":\"structRedelegationEntry[]\",\"name\":\"entries\",\"type\":\"tuple[]\"}],\"internalType\":\"structRedelegation\",\"name\":\"redelegation\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"int64\",\"name\":\"creationHeight\",\"type\":\"int64\"},{\"internalType\":\"int64\",\"name\":\"completionTime\",\"type\":\"int64\"},{\"internalType\":\"uint256\",\"name\":\"initialBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"sharesDst\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"unbondingId\",\"type\":\"uint64\"},{\"internalType\":\"int64\",\"name\":\"unbondingOnHoldRefCount\",\"type\":\"int64\"}],\"internalType\":\"structRedelegationEntry\",\"name\":\"redelegationEntry\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"internalType\":\"structRedelegationEntryResponse[]\",\"name\":\"entries\",\"type\":\"tuple[]\"}],\"internalType\":\"structRedelegationResponse[]\",\"name\":\"redelegationResponses\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"nextKey\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"total\",\"type\":\"uint64\"}],\"internalType\":\"structPageResponse\",\"name\":\"paginationResult\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"delegatorAddr\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"validatorAddr\",\"type\":\"string\"}],\"name\":\"unbondingDelegation\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"delegatorAddress\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"validatorAddress\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"creationHeight\",\"type\":\"int64\"},{\"internalType\":\"int64\",\"name\":\"completionTime\",\"type\":\"int64\"},{\"internalType\":\"uint256\",\"name\":\"initialBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"unbondingId\",\"type\":\"uint64\"},{\"internalType\":\"int64\",\"name\":\"unbondingOnHoldRefCount\",\"type\":\"int64\"}],\"internalType\":\"structUnbondingDelegationEntry[]\",\"name\":\"entries\",\"type\":\"tuple[]\"}],\"internalType\":\"structUnbondingDelegation\",\"name\":\"unbond\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"validatorAddress\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"undelegate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"completionTime\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"validatorAddress\",\"type\":\"string\"}],\"name\":\"validator\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"operatorAddress\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"consensusPubkey\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"jailed\",\"type\":\"bool\"},{\"internalType\":\"enumBondStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"delegatorShares\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"moniker\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"identity\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"website\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"securityContact\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"details\",\"type\":\"string\"}],\"internalType\":\"structDescription\",\"name\":\"description\",\"type\":\"tuple\"},{\"internalType\":\"int64\",\"name\":\"unbondingHeight\",\"type\":\"int64\"},{\"internalType\":\"int64\",\"name\":\"unbondingTime\",\"type\":\"int64\"},{\"components\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"rate\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxRate\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxChangeRate\",\"type\":\"uint256\"}],\"internalType\":\"structCommissionRates\",\"name\":\"commissionRates\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"updateTime\",\"type\":\"uint256\"}],\"internalType\":\"structCommission\",\"name\":\"commission\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"minSelfDelegation\",\"type\":\"uint256\"},{\"internalType\":\"int64\",\"name\":\"unbondingOnHoldRefCount\",\"type\":\"int64\"},{\"internalType\":\"uint64[]\",\"name\":\"unbondingIds\",\"type\":\"uint64[]\"}],\"internalType\":\"structValidator\",\"name\":\"validator\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"validatorAddr\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"key\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offset\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"limit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"countTotal\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reverse\",\"type\":\"bool\"}],\"internalType\":\"structPageRequest\",\"name\":\"pagination\",\"type\":\"tuple\"}],\"name\":\"validatorDelegations\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"delegatorAddress\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"validatorAddress\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"shares\",\"type\":\"uint256\"}],\"internalType\":\"structDelegation\",\"name\":\"delegation\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"internalType\":\"structDelegationResponse[]\",\"name\":\"delegationResponses\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"nextKey\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"total\",\"type\":\"uint64\"}],\"internalType\":\"structPageResponse\",\"name\":\"paginationResult\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"validatorAddr\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"key\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offset\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"limit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"countTotal\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reverse\",\"type\":\"bool\"}],\"internalType\":\"structPageRequest\",\"name\":\"pagination\",\"type\":\"tuple\"}],\"name\":\"validatorUnbondingDelegations\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"delegatorAddress\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"validatorAddress\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"creationHeight\",\"type\":\"int64\"},{\"internalType\":\"int64\",\"name\":\"completionTime\",\"type\":\"int64\"},{\"internalType\":\"uint256\",\"name\":\"initialBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"unbondingId\",\"type\":\"uint64\"},{\"internalType\":\"int64\",\"name\":\"unbondingOnHoldRefCount\",\"type\":\"int64\"}],\"internalType\":\"structUnbondingDelegationEntry[]\",\"name\":\"entries\",\"type\":\"tuple[]\"}],\"internalType\":\"structUnbondingDelegation[]\",\"name\":\"unbondingResponses\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"nextKey\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"total\",\"type\":\"uint64\"}],\"internalType\":\"structPageResponse\",\"name\":\"paginationResult\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"status\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"key\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offset\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"limit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"countTotal\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reverse\",\"type\":\"bool\"}],\"internalType\":\"structPageRequest\",\"name\":\"pagination\",\"type\":\"tuple\"}],\"name\":\"validators\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"operatorAddress\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"consensusPubkey\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"jailed\",\"type\":\"bool\"},{\"internalType\":\"enumBondStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"delegatorShares\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"moniker\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"identity\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"website\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"securityContact\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"details\",\"type\":\"string\"}],\"internalType\":\"structDescription\",\"name\":\"description\",\"type\":\"tuple\"},{\"internalType\":\"int64\",\"name\":\"unbondingHeight\",\"type\":\"int64\"},{\"internalType\":\"int64\",\"name\":\"unbondingTime\",\"type\":\"int64\"},{\"components\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"rate\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxRate\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxChangeRate\",\"type\":\"uint256\"}],\"internalType\":\"structCommissionRates\",\"name\":\"commissionRates\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"updateTime\",\"type\":\"uint256\"}],\"internalType\":\"structCommission\",\"name\":\"commission\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"minSelfDelegation\",\"type\":\"uint256\"},{\"internalType\":\"int64\",\"name\":\"unbondingOnHoldRefCount\",\"type\":\"int64\"},{\"internalType\":\"uint64[]\",\"name\":\"unbondingIds\",\"type\":\"uint64[]\"}],\"internalType\":\"structValidator[]\",\"name\":\"validators\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"nextKey\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"total\",\"type\":\"uint64\"}],\"internalType\":\"structPageResponse\",\"name\":\"paginationResult\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", +} + +// StakingABI is the input ABI used to generate the binding from. +// Deprecated: Use StakingMetaData.ABI instead. +var StakingABI = StakingMetaData.ABI + +// Staking is an auto generated Go binding around an Ethereum contract. +type Staking struct { + StakingCaller // Read-only binding to the contract + StakingTransactor // Write-only binding to the contract + StakingFilterer // Log filterer for contract events +} + +// StakingCaller is an auto generated read-only Go binding around an Ethereum contract. +type StakingCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// StakingTransactor is an auto generated write-only Go binding around an Ethereum contract. +type StakingTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// StakingFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type StakingFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// StakingSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type StakingSession struct { + Contract *Staking // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// StakingCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type StakingCallerSession struct { + Contract *StakingCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// StakingTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type StakingTransactorSession struct { + Contract *StakingTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// StakingRaw is an auto generated low-level Go binding around an Ethereum contract. +type StakingRaw struct { + Contract *Staking // Generic contract binding to access the raw methods on +} + +// StakingCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type StakingCallerRaw struct { + Contract *StakingCaller // Generic read-only contract binding to access the raw methods on +} + +// StakingTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type StakingTransactorRaw struct { + Contract *StakingTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewStaking creates a new instance of Staking, bound to a specific deployed contract. +func NewStaking(address common.Address, backend bind.ContractBackend) (*Staking, error) { + contract, err := bindStaking(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Staking{StakingCaller: StakingCaller{contract: contract}, StakingTransactor: StakingTransactor{contract: contract}, StakingFilterer: StakingFilterer{contract: contract}}, nil +} + +// NewStakingCaller creates a new read-only instance of Staking, bound to a specific deployed contract. +func NewStakingCaller(address common.Address, caller bind.ContractCaller) (*StakingCaller, error) { + contract, err := bindStaking(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &StakingCaller{contract: contract}, nil +} + +// NewStakingTransactor creates a new write-only instance of Staking, bound to a specific deployed contract. +func NewStakingTransactor(address common.Address, transactor bind.ContractTransactor) (*StakingTransactor, error) { + contract, err := bindStaking(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &StakingTransactor{contract: contract}, nil +} + +// NewStakingFilterer creates a new log filterer instance of Staking, bound to a specific deployed contract. +func NewStakingFilterer(address common.Address, filterer bind.ContractFilterer) (*StakingFilterer, error) { + contract, err := bindStaking(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &StakingFilterer{contract: contract}, nil +} + +// bindStaking binds a generic wrapper to an already deployed contract. +func bindStaking(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(StakingABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Staking *StakingRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Staking.Contract.StakingCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Staking *StakingRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Staking.Contract.StakingTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Staking *StakingRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Staking.Contract.StakingTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Staking *StakingCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Staking.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Staking *StakingTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Staking.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Staking *StakingTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Staking.Contract.contract.Transact(opts, method, params...) +} + +// Delegation is a free data retrieval call binding the contract method 0x25b8eda2. +// +// Solidity: function delegation(string delegatorAddr, string validatorAddr) view returns((string,string,uint256) delegation, uint256 balance) +func (_Staking *StakingCaller) Delegation(opts *bind.CallOpts, delegatorAddr string, validatorAddr string) (struct { + Delegation Delegation + Balance *big.Int +}, error) { + var out []interface{} + err := _Staking.contract.Call(opts, &out, "delegation", delegatorAddr, validatorAddr) + + outstruct := new(struct { + Delegation Delegation + Balance *big.Int + }) + if err != nil { + return *outstruct, err + } + + outstruct.Delegation = *abi.ConvertType(out[0], new(Delegation)).(*Delegation) + outstruct.Balance = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + + return *outstruct, err + +} + +// Delegation is a free data retrieval call binding the contract method 0x25b8eda2. +// +// Solidity: function delegation(string delegatorAddr, string validatorAddr) view returns((string,string,uint256) delegation, uint256 balance) +func (_Staking *StakingSession) Delegation(delegatorAddr string, validatorAddr string) (struct { + Delegation Delegation + Balance *big.Int +}, error) { + return _Staking.Contract.Delegation(&_Staking.CallOpts, delegatorAddr, validatorAddr) +} + +// Delegation is a free data retrieval call binding the contract method 0x25b8eda2. +// +// Solidity: function delegation(string delegatorAddr, string validatorAddr) view returns((string,string,uint256) delegation, uint256 balance) +func (_Staking *StakingCallerSession) Delegation(delegatorAddr string, validatorAddr string) (struct { + Delegation Delegation + Balance *big.Int +}, error) { + return _Staking.Contract.Delegation(&_Staking.CallOpts, delegatorAddr, validatorAddr) +} + +// DelegatorDelegations is a free data retrieval call binding the contract method 0x062cac23. +// +// Solidity: function delegatorDelegations(string delegatorAddr, (bytes,uint64,uint64,bool,bool) pagination) view returns(((string,string,uint256),uint256)[] delegationResponses, (bytes,uint64) paginationResult) +func (_Staking *StakingCaller) DelegatorDelegations(opts *bind.CallOpts, delegatorAddr string, pagination PageRequest) (struct { + DelegationResponses []DelegationResponse + PaginationResult PageResponse +}, error) { + var out []interface{} + err := _Staking.contract.Call(opts, &out, "delegatorDelegations", delegatorAddr, pagination) + + outstruct := new(struct { + DelegationResponses []DelegationResponse + PaginationResult PageResponse + }) + if err != nil { + return *outstruct, err + } + + outstruct.DelegationResponses = *abi.ConvertType(out[0], new([]DelegationResponse)).(*[]DelegationResponse) + outstruct.PaginationResult = *abi.ConvertType(out[1], new(PageResponse)).(*PageResponse) + + return *outstruct, err + +} + +// DelegatorDelegations is a free data retrieval call binding the contract method 0x062cac23. +// +// Solidity: function delegatorDelegations(string delegatorAddr, (bytes,uint64,uint64,bool,bool) pagination) view returns(((string,string,uint256),uint256)[] delegationResponses, (bytes,uint64) paginationResult) +func (_Staking *StakingSession) DelegatorDelegations(delegatorAddr string, pagination PageRequest) (struct { + DelegationResponses []DelegationResponse + PaginationResult PageResponse +}, error) { + return _Staking.Contract.DelegatorDelegations(&_Staking.CallOpts, delegatorAddr, pagination) +} + +// DelegatorDelegations is a free data retrieval call binding the contract method 0x062cac23. +// +// Solidity: function delegatorDelegations(string delegatorAddr, (bytes,uint64,uint64,bool,bool) pagination) view returns(((string,string,uint256),uint256)[] delegationResponses, (bytes,uint64) paginationResult) +func (_Staking *StakingCallerSession) DelegatorDelegations(delegatorAddr string, pagination PageRequest) (struct { + DelegationResponses []DelegationResponse + PaginationResult PageResponse +}, error) { + return _Staking.Contract.DelegatorDelegations(&_Staking.CallOpts, delegatorAddr, pagination) +} + +// DelegatorUnbondingDelegations is a free data retrieval call binding the contract method 0xba157bc5. +// +// Solidity: function delegatorUnbondingDelegations(string delegatorAddr, (bytes,uint64,uint64,bool,bool) pagination) view returns((string,string,(int64,int64,uint256,uint256,uint64,int64)[])[] unbondingResponses, (bytes,uint64) paginationResult) +func (_Staking *StakingCaller) DelegatorUnbondingDelegations(opts *bind.CallOpts, delegatorAddr string, pagination PageRequest) (struct { + UnbondingResponses []UnbondingDelegation + PaginationResult PageResponse +}, error) { + var out []interface{} + err := _Staking.contract.Call(opts, &out, "delegatorUnbondingDelegations", delegatorAddr, pagination) + + outstruct := new(struct { + UnbondingResponses []UnbondingDelegation + PaginationResult PageResponse + }) + if err != nil { + return *outstruct, err + } + + outstruct.UnbondingResponses = *abi.ConvertType(out[0], new([]UnbondingDelegation)).(*[]UnbondingDelegation) + outstruct.PaginationResult = *abi.ConvertType(out[1], new(PageResponse)).(*PageResponse) + + return *outstruct, err + +} + +// DelegatorUnbondingDelegations is a free data retrieval call binding the contract method 0xba157bc5. +// +// Solidity: function delegatorUnbondingDelegations(string delegatorAddr, (bytes,uint64,uint64,bool,bool) pagination) view returns((string,string,(int64,int64,uint256,uint256,uint64,int64)[])[] unbondingResponses, (bytes,uint64) paginationResult) +func (_Staking *StakingSession) DelegatorUnbondingDelegations(delegatorAddr string, pagination PageRequest) (struct { + UnbondingResponses []UnbondingDelegation + PaginationResult PageResponse +}, error) { + return _Staking.Contract.DelegatorUnbondingDelegations(&_Staking.CallOpts, delegatorAddr, pagination) +} + +// DelegatorUnbondingDelegations is a free data retrieval call binding the contract method 0xba157bc5. +// +// Solidity: function delegatorUnbondingDelegations(string delegatorAddr, (bytes,uint64,uint64,bool,bool) pagination) view returns((string,string,(int64,int64,uint256,uint256,uint64,int64)[])[] unbondingResponses, (bytes,uint64) paginationResult) +func (_Staking *StakingCallerSession) DelegatorUnbondingDelegations(delegatorAddr string, pagination PageRequest) (struct { + UnbondingResponses []UnbondingDelegation + PaginationResult PageResponse +}, error) { + return _Staking.Contract.DelegatorUnbondingDelegations(&_Staking.CallOpts, delegatorAddr, pagination) +} + +// DelegatorValidator is a free data retrieval call binding the contract method 0x4118fcc0. +// +// Solidity: function delegatorValidator(string delegatorAddr, string validatorAddr) view returns((string,string,bool,uint8,uint256,uint256,(string,string,string,string,string),int64,int64,((uint256,uint256,uint256),uint256),uint256,int64,uint64[]) validator) +func (_Staking *StakingCaller) DelegatorValidator(opts *bind.CallOpts, delegatorAddr string, validatorAddr string) (Validator, error) { + var out []interface{} + err := _Staking.contract.Call(opts, &out, "delegatorValidator", delegatorAddr, validatorAddr) + + if err != nil { + return *new(Validator), err + } + + out0 := *abi.ConvertType(out[0], new(Validator)).(*Validator) + + return out0, err + +} + +// DelegatorValidator is a free data retrieval call binding the contract method 0x4118fcc0. +// +// Solidity: function delegatorValidator(string delegatorAddr, string validatorAddr) view returns((string,string,bool,uint8,uint256,uint256,(string,string,string,string,string),int64,int64,((uint256,uint256,uint256),uint256),uint256,int64,uint64[]) validator) +func (_Staking *StakingSession) DelegatorValidator(delegatorAddr string, validatorAddr string) (Validator, error) { + return _Staking.Contract.DelegatorValidator(&_Staking.CallOpts, delegatorAddr, validatorAddr) +} + +// DelegatorValidator is a free data retrieval call binding the contract method 0x4118fcc0. +// +// Solidity: function delegatorValidator(string delegatorAddr, string validatorAddr) view returns((string,string,bool,uint8,uint256,uint256,(string,string,string,string,string),int64,int64,((uint256,uint256,uint256),uint256),uint256,int64,uint64[]) validator) +func (_Staking *StakingCallerSession) DelegatorValidator(delegatorAddr string, validatorAddr string) (Validator, error) { + return _Staking.Contract.DelegatorValidator(&_Staking.CallOpts, delegatorAddr, validatorAddr) +} + +// DelegatorValidators is a free data retrieval call binding the contract method 0x0d4d2384. +// +// Solidity: function delegatorValidators(string delegatorAddr, (bytes,uint64,uint64,bool,bool) pagination) view returns((string,string,bool,uint8,uint256,uint256,(string,string,string,string,string),int64,int64,((uint256,uint256,uint256),uint256),uint256,int64,uint64[])[] validators, (bytes,uint64) paginationResult) +func (_Staking *StakingCaller) DelegatorValidators(opts *bind.CallOpts, delegatorAddr string, pagination PageRequest) (struct { + Validators []Validator + PaginationResult PageResponse +}, error) { + var out []interface{} + err := _Staking.contract.Call(opts, &out, "delegatorValidators", delegatorAddr, pagination) + + outstruct := new(struct { + Validators []Validator + PaginationResult PageResponse + }) + if err != nil { + return *outstruct, err + } + + outstruct.Validators = *abi.ConvertType(out[0], new([]Validator)).(*[]Validator) + outstruct.PaginationResult = *abi.ConvertType(out[1], new(PageResponse)).(*PageResponse) + + return *outstruct, err + +} + +// DelegatorValidators is a free data retrieval call binding the contract method 0x0d4d2384. +// +// Solidity: function delegatorValidators(string delegatorAddr, (bytes,uint64,uint64,bool,bool) pagination) view returns((string,string,bool,uint8,uint256,uint256,(string,string,string,string,string),int64,int64,((uint256,uint256,uint256),uint256),uint256,int64,uint64[])[] validators, (bytes,uint64) paginationResult) +func (_Staking *StakingSession) DelegatorValidators(delegatorAddr string, pagination PageRequest) (struct { + Validators []Validator + PaginationResult PageResponse +}, error) { + return _Staking.Contract.DelegatorValidators(&_Staking.CallOpts, delegatorAddr, pagination) +} + +// DelegatorValidators is a free data retrieval call binding the contract method 0x0d4d2384. +// +// Solidity: function delegatorValidators(string delegatorAddr, (bytes,uint64,uint64,bool,bool) pagination) view returns((string,string,bool,uint8,uint256,uint256,(string,string,string,string,string),int64,int64,((uint256,uint256,uint256),uint256),uint256,int64,uint64[])[] validators, (bytes,uint64) paginationResult) +func (_Staking *StakingCallerSession) DelegatorValidators(delegatorAddr string, pagination PageRequest) (struct { + Validators []Validator + PaginationResult PageResponse +}, error) { + return _Staking.Contract.DelegatorValidators(&_Staking.CallOpts, delegatorAddr, pagination) +} + +// Params is a free data retrieval call binding the contract method 0xcff0ab96. +// +// Solidity: function params() view returns((int64,uint32,uint32,uint32,string,uint256) params) +func (_Staking *StakingCaller) Params(opts *bind.CallOpts) (Params, error) { + var out []interface{} + err := _Staking.contract.Call(opts, &out, "params") + + if err != nil { + return *new(Params), err + } + + out0 := *abi.ConvertType(out[0], new(Params)).(*Params) + + return out0, err + +} + +// Params is a free data retrieval call binding the contract method 0xcff0ab96. +// +// Solidity: function params() view returns((int64,uint32,uint32,uint32,string,uint256) params) +func (_Staking *StakingSession) Params() (Params, error) { + return _Staking.Contract.Params(&_Staking.CallOpts) +} + +// Params is a free data retrieval call binding the contract method 0xcff0ab96. +// +// Solidity: function params() view returns((int64,uint32,uint32,uint32,string,uint256) params) +func (_Staking *StakingCallerSession) Params() (Params, error) { + return _Staking.Contract.Params(&_Staking.CallOpts) +} + +// Pool is a free data retrieval call binding the contract method 0x16f0115b. +// +// Solidity: function pool() view returns(uint256 notBondedTokens, uint256 bondedTokens) +func (_Staking *StakingCaller) Pool(opts *bind.CallOpts) (struct { + NotBondedTokens *big.Int + BondedTokens *big.Int +}, error) { + var out []interface{} + err := _Staking.contract.Call(opts, &out, "pool") + + outstruct := new(struct { + NotBondedTokens *big.Int + BondedTokens *big.Int + }) + if err != nil { + return *outstruct, err + } + + outstruct.NotBondedTokens = *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + outstruct.BondedTokens = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + + return *outstruct, err + +} + +// Pool is a free data retrieval call binding the contract method 0x16f0115b. +// +// Solidity: function pool() view returns(uint256 notBondedTokens, uint256 bondedTokens) +func (_Staking *StakingSession) Pool() (struct { + NotBondedTokens *big.Int + BondedTokens *big.Int +}, error) { + return _Staking.Contract.Pool(&_Staking.CallOpts) +} + +// Pool is a free data retrieval call binding the contract method 0x16f0115b. +// +// Solidity: function pool() view returns(uint256 notBondedTokens, uint256 bondedTokens) +func (_Staking *StakingCallerSession) Pool() (struct { + NotBondedTokens *big.Int + BondedTokens *big.Int +}, error) { + return _Staking.Contract.Pool(&_Staking.CallOpts) +} + +// Redelegations is a free data retrieval call binding the contract method 0xe4227092. +// +// Solidity: function redelegations(string delegatorAddress, string srcValidatorAddress, string dstValidatorAddress, (bytes,uint64,uint64,bool,bool) pageRequest) view returns(((string,string,string,(int64,int64,uint256,uint256,uint64,int64)[]),((int64,int64,uint256,uint256,uint64,int64),uint256)[])[] redelegationResponses, (bytes,uint64) paginationResult) +func (_Staking *StakingCaller) Redelegations(opts *bind.CallOpts, delegatorAddress string, srcValidatorAddress string, dstValidatorAddress string, pageRequest PageRequest) (struct { + RedelegationResponses []RedelegationResponse + PaginationResult PageResponse +}, error) { + var out []interface{} + err := _Staking.contract.Call(opts, &out, "redelegations", delegatorAddress, srcValidatorAddress, dstValidatorAddress, pageRequest) + + outstruct := new(struct { + RedelegationResponses []RedelegationResponse + PaginationResult PageResponse + }) + if err != nil { + return *outstruct, err + } + + outstruct.RedelegationResponses = *abi.ConvertType(out[0], new([]RedelegationResponse)).(*[]RedelegationResponse) + outstruct.PaginationResult = *abi.ConvertType(out[1], new(PageResponse)).(*PageResponse) + + return *outstruct, err + +} + +// Redelegations is a free data retrieval call binding the contract method 0xe4227092. +// +// Solidity: function redelegations(string delegatorAddress, string srcValidatorAddress, string dstValidatorAddress, (bytes,uint64,uint64,bool,bool) pageRequest) view returns(((string,string,string,(int64,int64,uint256,uint256,uint64,int64)[]),((int64,int64,uint256,uint256,uint64,int64),uint256)[])[] redelegationResponses, (bytes,uint64) paginationResult) +func (_Staking *StakingSession) Redelegations(delegatorAddress string, srcValidatorAddress string, dstValidatorAddress string, pageRequest PageRequest) (struct { + RedelegationResponses []RedelegationResponse + PaginationResult PageResponse +}, error) { + return _Staking.Contract.Redelegations(&_Staking.CallOpts, delegatorAddress, srcValidatorAddress, dstValidatorAddress, pageRequest) +} + +// Redelegations is a free data retrieval call binding the contract method 0xe4227092. +// +// Solidity: function redelegations(string delegatorAddress, string srcValidatorAddress, string dstValidatorAddress, (bytes,uint64,uint64,bool,bool) pageRequest) view returns(((string,string,string,(int64,int64,uint256,uint256,uint64,int64)[]),((int64,int64,uint256,uint256,uint64,int64),uint256)[])[] redelegationResponses, (bytes,uint64) paginationResult) +func (_Staking *StakingCallerSession) Redelegations(delegatorAddress string, srcValidatorAddress string, dstValidatorAddress string, pageRequest PageRequest) (struct { + RedelegationResponses []RedelegationResponse + PaginationResult PageResponse +}, error) { + return _Staking.Contract.Redelegations(&_Staking.CallOpts, delegatorAddress, srcValidatorAddress, dstValidatorAddress, pageRequest) +} + +// UnbondingDelegation is a free data retrieval call binding the contract method 0x20bc02be. +// +// Solidity: function unbondingDelegation(string delegatorAddr, string validatorAddr) view returns((string,string,(int64,int64,uint256,uint256,uint64,int64)[]) unbond) +func (_Staking *StakingCaller) UnbondingDelegation(opts *bind.CallOpts, delegatorAddr string, validatorAddr string) (UnbondingDelegation, error) { + var out []interface{} + err := _Staking.contract.Call(opts, &out, "unbondingDelegation", delegatorAddr, validatorAddr) + + if err != nil { + return *new(UnbondingDelegation), err + } + + out0 := *abi.ConvertType(out[0], new(UnbondingDelegation)).(*UnbondingDelegation) + + return out0, err + +} + +// UnbondingDelegation is a free data retrieval call binding the contract method 0x20bc02be. +// +// Solidity: function unbondingDelegation(string delegatorAddr, string validatorAddr) view returns((string,string,(int64,int64,uint256,uint256,uint64,int64)[]) unbond) +func (_Staking *StakingSession) UnbondingDelegation(delegatorAddr string, validatorAddr string) (UnbondingDelegation, error) { + return _Staking.Contract.UnbondingDelegation(&_Staking.CallOpts, delegatorAddr, validatorAddr) +} + +// UnbondingDelegation is a free data retrieval call binding the contract method 0x20bc02be. +// +// Solidity: function unbondingDelegation(string delegatorAddr, string validatorAddr) view returns((string,string,(int64,int64,uint256,uint256,uint64,int64)[]) unbond) +func (_Staking *StakingCallerSession) UnbondingDelegation(delegatorAddr string, validatorAddr string) (UnbondingDelegation, error) { + return _Staking.Contract.UnbondingDelegation(&_Staking.CallOpts, delegatorAddr, validatorAddr) +} + +// Validator is a free data retrieval call binding the contract method 0x0bc82a17. +// +// Solidity: function validator(string validatorAddress) view returns((string,string,bool,uint8,uint256,uint256,(string,string,string,string,string),int64,int64,((uint256,uint256,uint256),uint256),uint256,int64,uint64[]) validator) +func (_Staking *StakingCaller) Validator(opts *bind.CallOpts, validatorAddress string) (Validator, error) { + var out []interface{} + err := _Staking.contract.Call(opts, &out, "validator", validatorAddress) + + if err != nil { + return *new(Validator), err + } + + out0 := *abi.ConvertType(out[0], new(Validator)).(*Validator) + + return out0, err + +} + +// Validator is a free data retrieval call binding the contract method 0x0bc82a17. +// +// Solidity: function validator(string validatorAddress) view returns((string,string,bool,uint8,uint256,uint256,(string,string,string,string,string),int64,int64,((uint256,uint256,uint256),uint256),uint256,int64,uint64[]) validator) +func (_Staking *StakingSession) Validator(validatorAddress string) (Validator, error) { + return _Staking.Contract.Validator(&_Staking.CallOpts, validatorAddress) +} + +// Validator is a free data retrieval call binding the contract method 0x0bc82a17. +// +// Solidity: function validator(string validatorAddress) view returns((string,string,bool,uint8,uint256,uint256,(string,string,string,string,string),int64,int64,((uint256,uint256,uint256),uint256),uint256,int64,uint64[]) validator) +func (_Staking *StakingCallerSession) Validator(validatorAddress string) (Validator, error) { + return _Staking.Contract.Validator(&_Staking.CallOpts, validatorAddress) +} + +// ValidatorDelegations is a free data retrieval call binding the contract method 0x85cadbda. +// +// Solidity: function validatorDelegations(string validatorAddr, (bytes,uint64,uint64,bool,bool) pagination) view returns(((string,string,uint256),uint256)[] delegationResponses, (bytes,uint64) paginationResult) +func (_Staking *StakingCaller) ValidatorDelegations(opts *bind.CallOpts, validatorAddr string, pagination PageRequest) (struct { + DelegationResponses []DelegationResponse + PaginationResult PageResponse +}, error) { + var out []interface{} + err := _Staking.contract.Call(opts, &out, "validatorDelegations", validatorAddr, pagination) + + outstruct := new(struct { + DelegationResponses []DelegationResponse + PaginationResult PageResponse + }) + if err != nil { + return *outstruct, err + } + + outstruct.DelegationResponses = *abi.ConvertType(out[0], new([]DelegationResponse)).(*[]DelegationResponse) + outstruct.PaginationResult = *abi.ConvertType(out[1], new(PageResponse)).(*PageResponse) + + return *outstruct, err + +} + +// ValidatorDelegations is a free data retrieval call binding the contract method 0x85cadbda. +// +// Solidity: function validatorDelegations(string validatorAddr, (bytes,uint64,uint64,bool,bool) pagination) view returns(((string,string,uint256),uint256)[] delegationResponses, (bytes,uint64) paginationResult) +func (_Staking *StakingSession) ValidatorDelegations(validatorAddr string, pagination PageRequest) (struct { + DelegationResponses []DelegationResponse + PaginationResult PageResponse +}, error) { + return _Staking.Contract.ValidatorDelegations(&_Staking.CallOpts, validatorAddr, pagination) +} + +// ValidatorDelegations is a free data retrieval call binding the contract method 0x85cadbda. +// +// Solidity: function validatorDelegations(string validatorAddr, (bytes,uint64,uint64,bool,bool) pagination) view returns(((string,string,uint256),uint256)[] delegationResponses, (bytes,uint64) paginationResult) +func (_Staking *StakingCallerSession) ValidatorDelegations(validatorAddr string, pagination PageRequest) (struct { + DelegationResponses []DelegationResponse + PaginationResult PageResponse +}, error) { + return _Staking.Contract.ValidatorDelegations(&_Staking.CallOpts, validatorAddr, pagination) +} + +// ValidatorUnbondingDelegations is a free data retrieval call binding the contract method 0x1394d67f. +// +// Solidity: function validatorUnbondingDelegations(string validatorAddr, (bytes,uint64,uint64,bool,bool) pagination) view returns((string,string,(int64,int64,uint256,uint256,uint64,int64)[])[] unbondingResponses, (bytes,uint64) paginationResult) +func (_Staking *StakingCaller) ValidatorUnbondingDelegations(opts *bind.CallOpts, validatorAddr string, pagination PageRequest) (struct { + UnbondingResponses []UnbondingDelegation + PaginationResult PageResponse +}, error) { + var out []interface{} + err := _Staking.contract.Call(opts, &out, "validatorUnbondingDelegations", validatorAddr, pagination) + + outstruct := new(struct { + UnbondingResponses []UnbondingDelegation + PaginationResult PageResponse + }) + if err != nil { + return *outstruct, err + } + + outstruct.UnbondingResponses = *abi.ConvertType(out[0], new([]UnbondingDelegation)).(*[]UnbondingDelegation) + outstruct.PaginationResult = *abi.ConvertType(out[1], new(PageResponse)).(*PageResponse) + + return *outstruct, err + +} + +// ValidatorUnbondingDelegations is a free data retrieval call binding the contract method 0x1394d67f. +// +// Solidity: function validatorUnbondingDelegations(string validatorAddr, (bytes,uint64,uint64,bool,bool) pagination) view returns((string,string,(int64,int64,uint256,uint256,uint64,int64)[])[] unbondingResponses, (bytes,uint64) paginationResult) +func (_Staking *StakingSession) ValidatorUnbondingDelegations(validatorAddr string, pagination PageRequest) (struct { + UnbondingResponses []UnbondingDelegation + PaginationResult PageResponse +}, error) { + return _Staking.Contract.ValidatorUnbondingDelegations(&_Staking.CallOpts, validatorAddr, pagination) +} + +// ValidatorUnbondingDelegations is a free data retrieval call binding the contract method 0x1394d67f. +// +// Solidity: function validatorUnbondingDelegations(string validatorAddr, (bytes,uint64,uint64,bool,bool) pagination) view returns((string,string,(int64,int64,uint256,uint256,uint64,int64)[])[] unbondingResponses, (bytes,uint64) paginationResult) +func (_Staking *StakingCallerSession) ValidatorUnbondingDelegations(validatorAddr string, pagination PageRequest) (struct { + UnbondingResponses []UnbondingDelegation + PaginationResult PageResponse +}, error) { + return _Staking.Contract.ValidatorUnbondingDelegations(&_Staking.CallOpts, validatorAddr, pagination) +} + +// Validators is a free data retrieval call binding the contract method 0x186b2167. +// +// Solidity: function validators(string status, (bytes,uint64,uint64,bool,bool) pagination) view returns((string,string,bool,uint8,uint256,uint256,(string,string,string,string,string),int64,int64,((uint256,uint256,uint256),uint256),uint256,int64,uint64[])[] validators, (bytes,uint64) paginationResult) +func (_Staking *StakingCaller) Validators(opts *bind.CallOpts, status string, pagination PageRequest) (struct { + Validators []Validator + PaginationResult PageResponse +}, error) { + var out []interface{} + err := _Staking.contract.Call(opts, &out, "validators", status, pagination) + + outstruct := new(struct { + Validators []Validator + PaginationResult PageResponse + }) + if err != nil { + return *outstruct, err + } + + outstruct.Validators = *abi.ConvertType(out[0], new([]Validator)).(*[]Validator) + outstruct.PaginationResult = *abi.ConvertType(out[1], new(PageResponse)).(*PageResponse) + + return *outstruct, err + +} + +// Validators is a free data retrieval call binding the contract method 0x186b2167. +// +// Solidity: function validators(string status, (bytes,uint64,uint64,bool,bool) pagination) view returns((string,string,bool,uint8,uint256,uint256,(string,string,string,string,string),int64,int64,((uint256,uint256,uint256),uint256),uint256,int64,uint64[])[] validators, (bytes,uint64) paginationResult) +func (_Staking *StakingSession) Validators(status string, pagination PageRequest) (struct { + Validators []Validator + PaginationResult PageResponse +}, error) { + return _Staking.Contract.Validators(&_Staking.CallOpts, status, pagination) +} + +// Validators is a free data retrieval call binding the contract method 0x186b2167. +// +// Solidity: function validators(string status, (bytes,uint64,uint64,bool,bool) pagination) view returns((string,string,bool,uint8,uint256,uint256,(string,string,string,string,string),int64,int64,((uint256,uint256,uint256),uint256),uint256,int64,uint64[])[] validators, (bytes,uint64) paginationResult) +func (_Staking *StakingCallerSession) Validators(status string, pagination PageRequest) (struct { + Validators []Validator + PaginationResult PageResponse +}, error) { + return _Staking.Contract.Validators(&_Staking.CallOpts, status, pagination) +} + +// BeginRedelegate is a paid mutator transaction binding the contract method 0x2e436cf2. +// +// Solidity: function beginRedelegate(string validatorSrcAddress, string validatorDstAddress, uint256 amount) returns(uint256 completionTime) +func (_Staking *StakingTransactor) BeginRedelegate(opts *bind.TransactOpts, validatorSrcAddress string, validatorDstAddress string, amount *big.Int) (*types.Transaction, error) { + return _Staking.contract.Transact(opts, "beginRedelegate", validatorSrcAddress, validatorDstAddress, amount) +} + +// BeginRedelegate is a paid mutator transaction binding the contract method 0x2e436cf2. +// +// Solidity: function beginRedelegate(string validatorSrcAddress, string validatorDstAddress, uint256 amount) returns(uint256 completionTime) +func (_Staking *StakingSession) BeginRedelegate(validatorSrcAddress string, validatorDstAddress string, amount *big.Int) (*types.Transaction, error) { + return _Staking.Contract.BeginRedelegate(&_Staking.TransactOpts, validatorSrcAddress, validatorDstAddress, amount) +} + +// BeginRedelegate is a paid mutator transaction binding the contract method 0x2e436cf2. +// +// Solidity: function beginRedelegate(string validatorSrcAddress, string validatorDstAddress, uint256 amount) returns(uint256 completionTime) +func (_Staking *StakingTransactorSession) BeginRedelegate(validatorSrcAddress string, validatorDstAddress string, amount *big.Int) (*types.Transaction, error) { + return _Staking.Contract.BeginRedelegate(&_Staking.TransactOpts, validatorSrcAddress, validatorDstAddress, amount) +} + +// CancelUnbondingDelegation is a paid mutator transaction binding the contract method 0x43970281. +// +// Solidity: function cancelUnbondingDelegation(string validatorAddress, uint256 amount, uint256 creationHeight) returns() +func (_Staking *StakingTransactor) CancelUnbondingDelegation(opts *bind.TransactOpts, validatorAddress string, amount *big.Int, creationHeight *big.Int) (*types.Transaction, error) { + return _Staking.contract.Transact(opts, "cancelUnbondingDelegation", validatorAddress, amount, creationHeight) +} + +// CancelUnbondingDelegation is a paid mutator transaction binding the contract method 0x43970281. +// +// Solidity: function cancelUnbondingDelegation(string validatorAddress, uint256 amount, uint256 creationHeight) returns() +func (_Staking *StakingSession) CancelUnbondingDelegation(validatorAddress string, amount *big.Int, creationHeight *big.Int) (*types.Transaction, error) { + return _Staking.Contract.CancelUnbondingDelegation(&_Staking.TransactOpts, validatorAddress, amount, creationHeight) +} + +// CancelUnbondingDelegation is a paid mutator transaction binding the contract method 0x43970281. +// +// Solidity: function cancelUnbondingDelegation(string validatorAddress, uint256 amount, uint256 creationHeight) returns() +func (_Staking *StakingTransactorSession) CancelUnbondingDelegation(validatorAddress string, amount *big.Int, creationHeight *big.Int) (*types.Transaction, error) { + return _Staking.Contract.CancelUnbondingDelegation(&_Staking.TransactOpts, validatorAddress, amount, creationHeight) +} + +// CreateValidator is a paid mutator transaction binding the contract method 0x3adeba1e. +// +// Solidity: function createValidator((string,string,string,string,string) description, (uint256,uint256,uint256) commission, uint256 minSelfDelegation, string pubkey, uint256 value) returns() +func (_Staking *StakingTransactor) CreateValidator(opts *bind.TransactOpts, description Description, commission CommissionRates, minSelfDelegation *big.Int, pubkey string, value *big.Int) (*types.Transaction, error) { + return _Staking.contract.Transact(opts, "createValidator", description, commission, minSelfDelegation, pubkey, value) +} + +// CreateValidator is a paid mutator transaction binding the contract method 0x3adeba1e. +// +// Solidity: function createValidator((string,string,string,string,string) description, (uint256,uint256,uint256) commission, uint256 minSelfDelegation, string pubkey, uint256 value) returns() +func (_Staking *StakingSession) CreateValidator(description Description, commission CommissionRates, minSelfDelegation *big.Int, pubkey string, value *big.Int) (*types.Transaction, error) { + return _Staking.Contract.CreateValidator(&_Staking.TransactOpts, description, commission, minSelfDelegation, pubkey, value) +} + +// CreateValidator is a paid mutator transaction binding the contract method 0x3adeba1e. +// +// Solidity: function createValidator((string,string,string,string,string) description, (uint256,uint256,uint256) commission, uint256 minSelfDelegation, string pubkey, uint256 value) returns() +func (_Staking *StakingTransactorSession) CreateValidator(description Description, commission CommissionRates, minSelfDelegation *big.Int, pubkey string, value *big.Int) (*types.Transaction, error) { + return _Staking.Contract.CreateValidator(&_Staking.TransactOpts, description, commission, minSelfDelegation, pubkey, value) +} + +// Delegate is a paid mutator transaction binding the contract method 0x03f24de1. +// +// Solidity: function delegate(string validatorAddress, uint256 amount) returns() +func (_Staking *StakingTransactor) Delegate(opts *bind.TransactOpts, validatorAddress string, amount *big.Int) (*types.Transaction, error) { + return _Staking.contract.Transact(opts, "delegate", validatorAddress, amount) +} + +// Delegate is a paid mutator transaction binding the contract method 0x03f24de1. +// +// Solidity: function delegate(string validatorAddress, uint256 amount) returns() +func (_Staking *StakingSession) Delegate(validatorAddress string, amount *big.Int) (*types.Transaction, error) { + return _Staking.Contract.Delegate(&_Staking.TransactOpts, validatorAddress, amount) +} + +// Delegate is a paid mutator transaction binding the contract method 0x03f24de1. +// +// Solidity: function delegate(string validatorAddress, uint256 amount) returns() +func (_Staking *StakingTransactorSession) Delegate(validatorAddress string, amount *big.Int) (*types.Transaction, error) { + return _Staking.Contract.Delegate(&_Staking.TransactOpts, validatorAddress, amount) +} + +// EditValidator is a paid mutator transaction binding the contract method 0x34397fbb. +// +// Solidity: function editValidator((string,string,string,string,string) description, (bool,uint256) commissionRate, (bool,uint256) minSelfDelegation) returns() +func (_Staking *StakingTransactor) EditValidator(opts *bind.TransactOpts, description Description, commissionRate NullableUint, minSelfDelegation NullableUint) (*types.Transaction, error) { + return _Staking.contract.Transact(opts, "editValidator", description, commissionRate, minSelfDelegation) +} + +// EditValidator is a paid mutator transaction binding the contract method 0x34397fbb. +// +// Solidity: function editValidator((string,string,string,string,string) description, (bool,uint256) commissionRate, (bool,uint256) minSelfDelegation) returns() +func (_Staking *StakingSession) EditValidator(description Description, commissionRate NullableUint, minSelfDelegation NullableUint) (*types.Transaction, error) { + return _Staking.Contract.EditValidator(&_Staking.TransactOpts, description, commissionRate, minSelfDelegation) +} + +// EditValidator is a paid mutator transaction binding the contract method 0x34397fbb. +// +// Solidity: function editValidator((string,string,string,string,string) description, (bool,uint256) commissionRate, (bool,uint256) minSelfDelegation) returns() +func (_Staking *StakingTransactorSession) EditValidator(description Description, commissionRate NullableUint, minSelfDelegation NullableUint) (*types.Transaction, error) { + return _Staking.Contract.EditValidator(&_Staking.TransactOpts, description, commissionRate, minSelfDelegation) +} + +// Undelegate is a paid mutator transaction binding the contract method 0x8dfc8897. +// +// Solidity: function undelegate(string validatorAddress, uint256 amount) returns(uint256 completionTime) +func (_Staking *StakingTransactor) Undelegate(opts *bind.TransactOpts, validatorAddress string, amount *big.Int) (*types.Transaction, error) { + return _Staking.contract.Transact(opts, "undelegate", validatorAddress, amount) +} + +// Undelegate is a paid mutator transaction binding the contract method 0x8dfc8897. +// +// Solidity: function undelegate(string validatorAddress, uint256 amount) returns(uint256 completionTime) +func (_Staking *StakingSession) Undelegate(validatorAddress string, amount *big.Int) (*types.Transaction, error) { + return _Staking.Contract.Undelegate(&_Staking.TransactOpts, validatorAddress, amount) +} + +// Undelegate is a paid mutator transaction binding the contract method 0x8dfc8897. +// +// Solidity: function undelegate(string validatorAddress, uint256 amount) returns(uint256 completionTime) +func (_Staking *StakingTransactorSession) Undelegate(validatorAddress string, amount *big.Int) (*types.Transaction, error) { + return _Staking.Contract.Undelegate(&_Staking.TransactOpts, validatorAddress, amount) +} diff --git a/precompiles/staking/errors.go b/precompiles/staking/errors.go new file mode 100644 index 00000000..c86fc858 --- /dev/null +++ b/precompiles/staking/errors.go @@ -0,0 +1,5 @@ +package staking + +const ( + ErrPubKeyInvalidLength = "public key with invalid length" +) diff --git a/precompiles/staking/query.go b/precompiles/staking/query.go new file mode 100644 index 00000000..610324ad --- /dev/null +++ b/precompiles/staking/query.go @@ -0,0 +1,223 @@ +package staking + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/core/vm" +) + +func (s *StakingPrecompile) Validators(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) { + req, err := NewQueryValidatorsRequest(args) + if err != nil { + return nil, err + } + response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.Validators(ctx, req) + if err != nil { + return nil, err + } + + validators := make([]Validator, len(response.Validators)) + for i, v := range response.Validators { + validators[i] = convertValidator(v) + } + paginationResult := convertPageResponse(response.Pagination) + + return method.Outputs.Pack(validators, paginationResult) +} + +func (s *StakingPrecompile) Validator(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) { + req, err := NewQueryValidatorRequest(args) + if err != nil { + return nil, err + } + response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.Validator(ctx, req) + if err != nil { + return nil, err + } + + return method.Outputs.Pack(convertValidator(response.Validator)) +} + +func (s *StakingPrecompile) ValidatorDelegations(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) { + req, err := NewQueryValidatorDelegationsRequest(args) + if err != nil { + return nil, err + } + response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.ValidatorDelegations(ctx, req) + if err != nil { + return nil, err + } + + delegationResponses := make([]DelegationResponse, len(response.DelegationResponses)) + for i, v := range response.DelegationResponses { + delegationResponses[i] = convertDelegationResponse(v) + } + paginationResult := convertPageResponse(response.Pagination) + + return method.Outputs.Pack(delegationResponses, paginationResult) +} + +func (s *StakingPrecompile) ValidatorUnbondingDelegations(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) { + req, err := NewQueryValidatorUnbondingDelegationsRequest(args) + if err != nil { + return nil, err + } + response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.ValidatorUnbondingDelegations(ctx, req) + if err != nil { + return nil, err + } + + unbondingResponses := make([]UnbondingDelegation, len(response.UnbondingResponses)) + for i, v := range response.UnbondingResponses { + unbondingResponses[i] = convertUnbondingDelegation(v) + } + paginationResult := convertPageResponse(response.Pagination) + + return method.Outputs.Pack(unbondingResponses, paginationResult) +} + +func (s *StakingPrecompile) Delegation(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) { + req, err := NewQueryDelegationRequest(args) + if err != nil { + return nil, err + } + response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.Delegation(ctx, req) + if err != nil { + return nil, err + } + delegation := convertDelegation(response.DelegationResponse.Delegation) + balance := response.DelegationResponse.Balance.Amount.BigInt() + + return method.Outputs.Pack(delegation, balance) +} + +func (s *StakingPrecompile) UnbondingDelegation(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) { + req, err := NewQueryUnbondingDelegationRequest(args) + if err != nil { + return nil, err + } + response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.UnbondingDelegation(ctx, req) + if err != nil { + return nil, err + } + + return method.Outputs.Pack(convertUnbondingDelegation(response.Unbond)) +} + +func (s *StakingPrecompile) DelegatorDelegations(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) { + req, err := NewQueryDelegatorDelegationsRequest(args) + if err != nil { + return nil, err + } + response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.DelegatorDelegations(ctx, req) + if err != nil { + return nil, err + } + + delegationResponses := make([]DelegationResponse, len(response.DelegationResponses)) + for i, v := range response.DelegationResponses { + delegationResponses[i] = convertDelegationResponse(v) + } + paginationResult := convertPageResponse(response.Pagination) + + return method.Outputs.Pack(delegationResponses, paginationResult) +} + +func (s *StakingPrecompile) DelegatorUnbondingDelegations(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) { + req, err := NewQueryDelegatorUnbondingDelegationsRequest(args) + if err != nil { + return nil, err + } + response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.DelegatorUnbondingDelegations(ctx, req) + if err != nil { + return nil, err + } + + unbondingResponses := make([]UnbondingDelegation, len(response.UnbondingResponses)) + for i, v := range response.UnbondingResponses { + unbondingResponses[i] = convertUnbondingDelegation(v) + } + paginationResult := convertPageResponse(response.Pagination) + + return method.Outputs.Pack(unbondingResponses, paginationResult) +} + +func (s *StakingPrecompile) Redelegations(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) { + req, err := NewQueryRedelegationsRequest(args) + if err != nil { + return nil, err + } + response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.Redelegations(ctx, req) + if err != nil { + return nil, err + } + + redelegationResponses := make([]RedelegationResponse, len(response.RedelegationResponses)) + for i, v := range response.RedelegationResponses { + redelegationResponses[i] = convertRedelegationResponse(v) + } + paginationResult := convertPageResponse(response.Pagination) + + return method.Outputs.Pack(redelegationResponses, paginationResult) +} + +func (s *StakingPrecompile) DelegatorValidators(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) { + req, err := NewQueryDelegatorValidatorsRequest(args) + if err != nil { + return nil, err + } + response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.DelegatorValidators(ctx, req) + if err != nil { + return nil, err + } + + validators := make([]Validator, len(response.Validators)) + for i, v := range response.Validators { + validators[i] = convertValidator(v) + } + paginationResult := convertPageResponse(response.Pagination) + + return method.Outputs.Pack(validators, paginationResult) +} + +func (s *StakingPrecompile) DelegatorValidator(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) { + req, err := NewQueryDelegatorValidatorRequest(args) + if err != nil { + return nil, err + } + response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.DelegatorValidator(ctx, req) + if err != nil { + return nil, err + } + + return method.Outputs.Pack(convertValidator(response.Validator)) +} + +func (s *StakingPrecompile) Pool(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) { + req, err := NewQueryPoolRequest(args) + if err != nil { + return nil, err + } + response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.Pool(ctx, req) + if err != nil { + return nil, err + } + notBondedTokens := response.Pool.NotBondedTokens.BigInt() + bondedTokens := response.Pool.BondedTokens.BigInt() + + return method.Outputs.Pack(notBondedTokens, bondedTokens) +} + +func (s *StakingPrecompile) Params(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) { + req, err := NewQueryParamsRequest(args) + if err != nil { + return nil, err + } + response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.Params(ctx, req) + if err != nil { + return nil, err + } + + return method.Outputs.Pack(convertParams(response.Params)) +} diff --git a/precompiles/staking/query_test.go b/precompiles/staking/query_test.go new file mode 100644 index 00000000..093446d7 --- /dev/null +++ b/precompiles/staking/query_test.go @@ -0,0 +1,801 @@ +package staking_test + +import ( + "math/big" + + stakingprecompile "github.com/0glabs/0g-chain/precompiles/staking" + sdk "github.com/cosmos/cosmos-sdk/types" + query "github.com/cosmos/cosmos-sdk/types/query" + "github.com/ethereum/go-ethereum/common" +) + +func (s *StakingTestSuite) TestValidators() { + method := stakingprecompile.StakingFunctionValidators + + testCases := []struct { + name string + malleate func() []byte + postCheck func(bz []byte) + gas uint64 + expErr bool + errContains string + }{ + { + "success", + func() []byte { + input, err := s.abi.Pack( + method, + "", + query.PageRequest{ + Limit: 10, + CountTotal: true, + }, + ) + s.Assert().NoError(err) + return input + }, + func(data []byte) { + out, err := s.abi.Methods[method].Outputs.Unpack(data) + s.Require().NoError(err, "failed to unpack output") + validators := out[0].([]stakingprecompile.Validator) + paginationResult := out[1].(stakingprecompile.PageResponse) + s.Assert().EqualValues(3, len(validators)) + s.Assert().EqualValues(3, paginationResult.Total) + }, + 100000, + false, + "", + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + s.SetupTest() + s.AddDelegation(s.signerOne.HexAddr, s.signerTwo.HexAddr, sdk.NewIntFromUint64(1000000)) + + bz, err := s.runTx(tc.malleate(), s.signerOne, 10000000) + + if tc.expErr { + s.Require().Error(err) + s.Require().Contains(err.Error(), tc.errContains) + } else { + s.Require().NoError(err) + s.Require().NotNil(bz) + tc.postCheck(bz) + } + }) + } +} + +func (s *StakingTestSuite) TestValidator() { + method := stakingprecompile.StakingFunctionValidator + + testCases := []struct { + name string + malleate func(operatorAddress string) []byte + postCheck func(bz []byte) + gas uint64 + expErr bool + errContains string + }{ + { + "success", + func(operatorAddress string) []byte { + input, err := s.abi.Pack( + method, + operatorAddress, + ) + s.Assert().NoError(err) + return input + }, + func(data []byte) { + out, err := s.abi.Methods[method].Outputs.Unpack(data) + s.Require().NoError(err, "failed to unpack output") + operatorAddress, err := s.firstBondedValidator() + s.Require().NoError(err) + validator := out[0].(stakingprecompile.Validator) + s.Require().EqualValues(common.HexToAddress(validator.OperatorAddress), common.BytesToAddress(operatorAddress.Bytes())) + }, + 100000, + false, + "", + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + s.SetupTest() + operatorAddress, err := s.firstBondedValidator() + s.Require().NoError(err) + + bz, err := s.runTx(tc.malleate(operatorAddress.String()), s.signerOne, 10000000) + + if tc.expErr { + s.Require().Error(err) + s.Require().Contains(err.Error(), tc.errContains) + } else { + s.Require().NoError(err) + s.Require().NotNil(bz) + tc.postCheck(bz) + } + }) + } +} + +func (s *StakingTestSuite) TestValidatorDelegations() { + method := stakingprecompile.StakingFunctionValidatorDelegations + + testCases := []struct { + name string + malleate func(operatorAddress string) []byte + postCheck func(bz []byte) + gas uint64 + expErr bool + errContains string + }{ + { + "success", + func(operatorAddress string) []byte { + input, err := s.abi.Pack( + method, + operatorAddress, + query.PageRequest{ + Limit: 10, + CountTotal: true, + }, + ) + s.Assert().NoError(err) + return input + }, + func(data []byte) { + out, err := s.abi.Methods[method].Outputs.Unpack(data) + s.Require().NoError(err, "failed to unpack output") + operatorAddress, err := s.firstBondedValidator() + s.Require().NoError(err) + delegations := out[0].([]stakingprecompile.DelegationResponse) + d := s.stakingKeeper.GetValidatorDelegations(s.Ctx, operatorAddress) + s.Require().EqualValues(len(delegations), len(d)) + // jsonData, _ := json.MarshalIndent(delegations, "", " ") + // fmt.Printf("delegations: %s\n", string(jsonData)) + }, + 100000, + false, + "", + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + s.SetupTest() + operatorAddress, err := s.firstBondedValidator() + s.Require().NoError(err) + + bz, err := s.runTx(tc.malleate(operatorAddress.String()), s.signerOne, 10000000) + + if tc.expErr { + s.Require().Error(err) + s.Require().Contains(err.Error(), tc.errContains) + } else { + s.Require().NoError(err) + s.Require().NotNil(bz) + tc.postCheck(bz) + } + }) + } +} + +func (s *StakingTestSuite) TestValidatorUnbondingDelegations() { + method := stakingprecompile.StakingFunctionValidatorUnbondingDelegations + + testCases := []struct { + name string + malleate func(operatorAddress string) []byte + postCheck func(bz []byte) + gas uint64 + expErr bool + errContains string + }{ + { + "success", + func(operatorAddress string) []byte { + input, err := s.abi.Pack( + method, + operatorAddress, + query.PageRequest{ + Limit: 10, + CountTotal: true, + }, + ) + s.Assert().NoError(err) + return input + }, + func(data []byte) { + out, err := s.abi.Methods[method].Outputs.Unpack(data) + s.Require().NoError(err, "failed to unpack output") + unbonding := out[0].([]stakingprecompile.UnbondingDelegation) + s.Require().EqualValues(len(unbonding), 1) + // jsonData, _ := json.MarshalIndent(unbonding, "", " ") + // fmt.Printf("delegations: %s\n", string(jsonData)) + }, + 100000, + false, + "", + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + s.SetupTest() + operatorAddress, err := s.firstBondedValidator() + s.Require().NoError(err) + d := s.stakingKeeper.GetValidatorDelegations(s.Ctx, operatorAddress) + delAddr, err := sdk.AccAddressFromBech32(d[0].DelegatorAddress) + s.Require().NoError(err) + _, err = s.stakingKeeper.Undelegate(s.Ctx, delAddr, operatorAddress, sdk.NewDec(1)) + s.Require().NoError(err) + + bz, err := s.runTx(tc.malleate(operatorAddress.String()), s.signerOne, 10000000) + + if tc.expErr { + s.Require().Error(err) + s.Require().Contains(err.Error(), tc.errContains) + } else { + s.Require().NoError(err) + s.Require().NotNil(bz) + tc.postCheck(bz) + } + }) + } +} + +func (s *StakingTestSuite) TestDelegation() { + method := stakingprecompile.StakingFunctionDelegation + + testCases := []struct { + name string + malleate func(delAddr, valAddr string) []byte + postCheck func(bz []byte) + gas uint64 + expErr bool + errContains string + }{ + { + "success", + func(delAddr, valAddr string) []byte { + input, err := s.abi.Pack( + method, + delAddr, + valAddr, + ) + s.Assert().NoError(err) + return input + }, + func(data []byte) { + out, err := s.abi.Methods[method].Outputs.Unpack(data) + s.Require().NoError(err, "failed to unpack output") + d := out[0].(stakingprecompile.Delegation) + b := out[1].(*big.Int) + _ = d + _ = b + /* + jsonData, _ := json.MarshalIndent(d, "", " ") + fmt.Printf("delegation: %s\n", string(jsonData)) + fmt.Printf("balance: %v\n", b) + */ + }, + 100000, + false, + "", + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + s.SetupTest() + operatorAddress, err := s.firstBondedValidator() + s.Require().NoError(err) + d := s.stakingKeeper.GetValidatorDelegations(s.Ctx, operatorAddress) + delAddr, err := sdk.AccAddressFromBech32(d[0].DelegatorAddress) + s.Require().NoError(err) + + bz, err := s.runTx(tc.malleate(delAddr.String(), operatorAddress.String()), s.signerOne, 10000000) + + if tc.expErr { + s.Require().Error(err) + s.Require().Contains(err.Error(), tc.errContains) + } else { + s.Require().NoError(err) + s.Require().NotNil(bz) + tc.postCheck(bz) + } + }) + } +} + +func (s *StakingTestSuite) TestUnbondingDelegation() { + method := stakingprecompile.StakingFunctionUnbondingDelegation + + testCases := []struct { + name string + malleate func(delAddr, valAddr string) []byte + postCheck func(bz []byte) + gas uint64 + expErr bool + errContains string + }{ + { + "success", + func(delAddr, valAddr string) []byte { + input, err := s.abi.Pack( + method, + delAddr, + valAddr, + ) + s.Assert().NoError(err) + return input + }, + func(data []byte) { + out, err := s.abi.Methods[method].Outputs.Unpack(data) + s.Require().NoError(err, "failed to unpack output") + u := out[0].(stakingprecompile.UnbondingDelegation) + _ = u + // jsonData, _ := json.MarshalIndent(u, "", " ") + // fmt.Printf("delegation: %s\n", string(jsonData)) + }, + 100000, + false, + "", + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + s.SetupTest() + operatorAddress, err := s.firstBondedValidator() + s.Require().NoError(err) + d := s.stakingKeeper.GetValidatorDelegations(s.Ctx, operatorAddress) + delAddr, err := sdk.AccAddressFromBech32(d[0].DelegatorAddress) + s.Require().NoError(err) + _, err = s.stakingKeeper.Undelegate(s.Ctx, delAddr, operatorAddress, sdk.NewDec(1)) + s.Require().NoError(err) + + bz, err := s.runTx(tc.malleate(delAddr.String(), operatorAddress.String()), s.signerOne, 10000000) + + if tc.expErr { + s.Require().Error(err) + s.Require().Contains(err.Error(), tc.errContains) + } else { + s.Require().NoError(err) + s.Require().NotNil(bz) + tc.postCheck(bz) + } + }) + } +} + +func (s *StakingTestSuite) TestDelegatorDelegations() { + method := stakingprecompile.StakingFunctionDelegatorDelegations + + testCases := []struct { + name string + malleate func(delAddr string) []byte + postCheck func(bz []byte) + gas uint64 + expErr bool + errContains string + }{ + { + "success", + func(delAddr string) []byte { + input, err := s.abi.Pack( + method, + delAddr, + query.PageRequest{ + Limit: 10, + CountTotal: true, + }, + ) + s.Assert().NoError(err) + return input + }, + func(data []byte) { + out, err := s.abi.Methods[method].Outputs.Unpack(data) + s.Require().NoError(err, "failed to unpack output") + d := out[0].([]stakingprecompile.DelegationResponse) + paginationResult := out[1].(stakingprecompile.PageResponse) + s.Assert().EqualValues(1, len(d)) + s.Assert().EqualValues(1, paginationResult.Total) + // jsonData, _ := json.MarshalIndent(d, "", " ") + // fmt.Printf("delegation: %s\n", string(jsonData)) + }, + 100000, + false, + "", + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + s.SetupTest() + operatorAddress, err := s.firstBondedValidator() + s.Require().NoError(err) + d := s.stakingKeeper.GetValidatorDelegations(s.Ctx, operatorAddress) + delAddr, err := sdk.AccAddressFromBech32(d[0].DelegatorAddress) + s.Require().NoError(err) + + bz, err := s.runTx(tc.malleate(delAddr.String()), s.signerOne, 10000000) + + if tc.expErr { + s.Require().Error(err) + s.Require().Contains(err.Error(), tc.errContains) + } else { + s.Require().NoError(err) + s.Require().NotNil(bz) + tc.postCheck(bz) + } + }) + } +} + +func (s *StakingTestSuite) TestDelegatorUnbondingDelegations() { + method := stakingprecompile.StakingFunctionDelegatorUnbondingDelegations + + testCases := []struct { + name string + malleate func(delAddr string) []byte + postCheck func(bz []byte) + gas uint64 + expErr bool + errContains string + }{ + { + "success", + func(delAddr string) []byte { + input, err := s.abi.Pack( + method, + delAddr, + query.PageRequest{ + Limit: 10, + CountTotal: true, + }, + ) + s.Assert().NoError(err) + return input + }, + func(data []byte) { + out, err := s.abi.Methods[method].Outputs.Unpack(data) + s.Require().NoError(err, "failed to unpack output") + d := out[0].([]stakingprecompile.UnbondingDelegation) + paginationResult := out[1].(stakingprecompile.PageResponse) + s.Assert().EqualValues(1, len(d)) + s.Assert().EqualValues(1, paginationResult.Total) + // jsonData, _ := json.MarshalIndent(d, "", " ") + // fmt.Printf("delegation: %s\n", string(jsonData)) + }, + 100000, + false, + "", + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + s.SetupTest() + operatorAddress, err := s.firstBondedValidator() + s.Require().NoError(err) + d := s.stakingKeeper.GetValidatorDelegations(s.Ctx, operatorAddress) + delAddr, err := sdk.AccAddressFromBech32(d[0].DelegatorAddress) + s.Require().NoError(err) + _, err = s.stakingKeeper.Undelegate(s.Ctx, delAddr, operatorAddress, sdk.NewDec(1)) + s.Require().NoError(err) + + bz, err := s.runTx(tc.malleate(delAddr.String()), s.signerOne, 10000000) + + if tc.expErr { + s.Require().Error(err) + s.Require().Contains(err.Error(), tc.errContains) + } else { + s.Require().NoError(err) + s.Require().NotNil(bz) + tc.postCheck(bz) + } + }) + } +} + +func (s *StakingTestSuite) TestRedelegations() { + method := stakingprecompile.StakingFunctionRedelegations + + testCases := []struct { + name string + malleate func(delAddr, srcValAddr, dstValAddr string) []byte + postCheck func(bz []byte) + gas uint64 + expErr bool + errContains string + }{ + { + "success", + func(delAddr, srcValAddr, dstValAddr string) []byte { + input, err := s.abi.Pack( + method, + delAddr, + srcValAddr, + dstValAddr, + query.PageRequest{ + Limit: 10, + CountTotal: true, + }, + ) + s.Assert().NoError(err) + return input + }, + func(data []byte) { + out, err := s.abi.Methods[method].Outputs.Unpack(data) + s.Require().NoError(err, "failed to unpack output") + d := out[0].([]stakingprecompile.RedelegationResponse) + paginationResult := out[1].(stakingprecompile.PageResponse) + s.Assert().EqualValues(1, len(d)) + s.Assert().EqualValues(1, paginationResult.Total) + // jsonData, _ := json.MarshalIndent(d, "", " ") + // fmt.Printf("redelegations: %s\n", string(jsonData)) + }, + 100000, + false, + "", + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + s.SetupTest() + operatorAddress, err := s.firstBondedValidator() + s.Require().NoError(err) + d := s.stakingKeeper.GetValidatorDelegations(s.Ctx, operatorAddress) + delAddr, err := sdk.AccAddressFromBech32(d[0].DelegatorAddress) + s.Require().NoError(err) + // setup redelegations + s.setupValidator(s.signerOne) + _, err = s.stakingKeeper.BeginRedelegation(s.Ctx, delAddr, operatorAddress, s.signerOne.ValAddr, sdk.NewDec(1)) + s.Require().NoError(err) + + bz, err := s.runTx(tc.malleate(delAddr.String(), operatorAddress.String(), s.signerOne.ValAddr.String()), s.signerOne, 10000000) + + if tc.expErr { + s.Require().Error(err) + s.Require().Contains(err.Error(), tc.errContains) + } else { + s.Require().NoError(err) + s.Require().NotNil(bz) + tc.postCheck(bz) + } + }) + } +} + +func (s *StakingTestSuite) TestDelegatorValidators() { + method := stakingprecompile.StakingFunctionDelegatorValidators + + testCases := []struct { + name string + malleate func(delAddr string) []byte + postCheck func(bz []byte) + gas uint64 + expErr bool + errContains string + }{ + { + "success", + func(delAddr string) []byte { + input, err := s.abi.Pack( + method, + delAddr, + query.PageRequest{ + Limit: 10, + CountTotal: true, + }, + ) + s.Assert().NoError(err) + return input + }, + func(data []byte) { + out, err := s.abi.Methods[method].Outputs.Unpack(data) + s.Require().NoError(err, "failed to unpack output") + v := out[0].([]stakingprecompile.Validator) + paginationResult := out[1].(stakingprecompile.PageResponse) + s.Assert().EqualValues(1, len(v)) + s.Assert().EqualValues(1, paginationResult.Total) + // jsonData, _ := json.MarshalIndent(v, "", " ") + // fmt.Printf("validators: %s\n", string(jsonData)) + }, + 100000, + false, + "", + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + s.SetupTest() + operatorAddress, err := s.firstBondedValidator() + s.Require().NoError(err) + d := s.stakingKeeper.GetValidatorDelegations(s.Ctx, operatorAddress) + delAddr, err := sdk.AccAddressFromBech32(d[0].DelegatorAddress) + s.Require().NoError(err) + + bz, err := s.runTx(tc.malleate(delAddr.String()), s.signerOne, 10000000) + + if tc.expErr { + s.Require().Error(err) + s.Require().Contains(err.Error(), tc.errContains) + } else { + s.Require().NoError(err) + s.Require().NotNil(bz) + tc.postCheck(bz) + } + }) + } +} + +func (s *StakingTestSuite) TestDelegatorValidator() { + method := stakingprecompile.StakingFunctionDelegatorValidator + + testCases := []struct { + name string + malleate func(delAddr, valAddr string) []byte + postCheck func(bz []byte) + gas uint64 + expErr bool + errContains string + }{ + { + "success", + func(delAddr, valAddr string) []byte { + input, err := s.abi.Pack( + method, + delAddr, + valAddr, + ) + s.Assert().NoError(err) + return input + }, + func(data []byte) { + out, err := s.abi.Methods[method].Outputs.Unpack(data) + s.Require().NoError(err, "failed to unpack output") + v := out[0].(stakingprecompile.Validator) + _ = v + // jsonData, _ := json.MarshalIndent(v, "", " ") + // fmt.Printf("validators: %s\n", string(jsonData)) + }, + 100000, + false, + "", + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + s.SetupTest() + operatorAddress, err := s.firstBondedValidator() + s.Require().NoError(err) + d := s.stakingKeeper.GetValidatorDelegations(s.Ctx, operatorAddress) + delAddr, err := sdk.AccAddressFromBech32(d[0].DelegatorAddress) + s.Require().NoError(err) + + bz, err := s.runTx(tc.malleate(delAddr.String(), operatorAddress.String()), s.signerOne, 10000000) + + if tc.expErr { + s.Require().Error(err) + s.Require().Contains(err.Error(), tc.errContains) + } else { + s.Require().NoError(err) + s.Require().NotNil(bz) + tc.postCheck(bz) + } + }) + } +} + +func (s *StakingTestSuite) TestPool() { + method := stakingprecompile.StakingFunctionPool + + testCases := []struct { + name string + malleate func() []byte + postCheck func(bz []byte) + gas uint64 + expErr bool + errContains string + }{ + { + "success", + func() []byte { + input, err := s.abi.Pack( + method, + ) + s.Assert().NoError(err) + return input + }, + func(data []byte) { + out, err := s.abi.Methods[method].Outputs.Unpack(data) + s.Require().NoError(err, "failed to unpack output") + bonded := out[0].(*big.Int) + unbonded := out[0].(*big.Int) + s.Assert().Equal(bonded.Int64(), int64(0)) + s.Assert().Equal(unbonded.Int64(), int64(0)) + }, + 100000, + false, + "", + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + s.SetupTest() + + bz, err := s.runTx(tc.malleate(), s.signerOne, 10000000) + + if tc.expErr { + s.Require().Error(err) + s.Require().Contains(err.Error(), tc.errContains) + } else { + s.Require().NoError(err) + s.Require().NotNil(bz) + tc.postCheck(bz) + } + }) + } +} + +func (s *StakingTestSuite) TestParams() { + method := stakingprecompile.StakingFunctionParams + + testCases := []struct { + name string + malleate func() []byte + postCheck func(bz []byte) + gas uint64 + expErr bool + errContains string + }{ + { + "success", + func() []byte { + input, err := s.abi.Pack( + method, + ) + s.Assert().NoError(err) + return input + }, + func(data []byte) { + out, err := s.abi.Methods[method].Outputs.Unpack(data) + s.Require().NoError(err, "failed to unpack output") + params := out[0].(stakingprecompile.Params) + _ = params + // jsonData, _ := json.MarshalIndent(params, "", " ") + // fmt.Printf("params: %s\n", string(jsonData)) + }, + 100000, + false, + "", + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + s.SetupTest() + + bz, err := s.runTx(tc.malleate(), s.signerOne, 10000000) + + if tc.expErr { + s.Require().Error(err) + s.Require().Contains(err.Error(), tc.errContains) + } else { + s.Require().NoError(err) + s.Require().NotNil(bz) + tc.postCheck(bz) + } + }) + } +} diff --git a/precompiles/staking/staking.go b/precompiles/staking/staking.go new file mode 100644 index 00000000..67d4a304 --- /dev/null +++ b/precompiles/staking/staking.go @@ -0,0 +1,148 @@ +package staking + +import ( + "fmt" + "strings" + + precopmiles_common "github.com/0glabs/0g-chain/precompiles/common" + "github.com/cosmos/cosmos-sdk/store/types" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/evmos/ethermint/x/evm/statedb" +) + +const ( + PrecompileAddress = "0x0000000000000000000000000000000000001001" + + // txs + StakingFunctionCreateValidator = "createValidator" + StakingFunctionEditValidator = "editValidator" + StakingFunctionDelegate = "delegate" + StakingFunctionBeginRedelegate = "beginRedelegate" + StakingFunctionUndelegate = "undelegate" + StakingFunctionCancelUnbondingDelegation = "cancelUnbondingDelegation" + // queries + StakingFunctionValidators = "validators" + StakingFunctionValidator = "validator" + StakingFunctionValidatorDelegations = "validatorDelegations" + StakingFunctionValidatorUnbondingDelegations = "validatorUnbondingDelegations" + StakingFunctionDelegation = "delegation" + StakingFunctionUnbondingDelegation = "unbondingDelegation" + StakingFunctionDelegatorDelegations = "delegatorDelegations" + StakingFunctionDelegatorUnbondingDelegations = "delegatorUnbondingDelegations" + StakingFunctionRedelegations = "redelegations" + StakingFunctionDelegatorValidators = "delegatorValidators" + StakingFunctionDelegatorValidator = "delegatorValidator" + StakingFunctionPool = "pool" + StakingFunctionParams = "params" +) + +var _ vm.PrecompiledContract = &StakingPrecompile{} + +type StakingPrecompile struct { + abi abi.ABI + stakingKeeper *stakingkeeper.Keeper +} + +func NewStakingPrecompile(stakingKeeper *stakingkeeper.Keeper) (*StakingPrecompile, error) { + abi, err := abi.JSON(strings.NewReader(StakingABI)) + if err != nil { + return nil, err + } + return &StakingPrecompile{ + abi: abi, + stakingKeeper: stakingKeeper, + }, nil +} + +// Address implements vm.PrecompiledContract. +func (s *StakingPrecompile) Address() common.Address { + return common.HexToAddress(PrecompileAddress) +} + +// RequiredGas implements vm.PrecompiledContract. +func (s *StakingPrecompile) RequiredGas(input []byte) uint64 { + return 0 +} + +// Run implements vm.PrecompiledContract. +func (s *StakingPrecompile) Run(evm *vm.EVM, contract *vm.Contract, readonly bool) ([]byte, error) { + // parse input + if len(contract.Input) < 4 { + return nil, vm.ErrExecutionReverted + } + method, err := s.abi.MethodById(contract.Input[:4]) + if err != nil { + return nil, vm.ErrExecutionReverted + } + args, err := method.Inputs.Unpack(contract.Input[4:]) + if err != nil { + return nil, err + } + // get state db and context + stateDB, ok := evm.StateDB.(*statedb.StateDB) + if !ok { + return nil, fmt.Errorf(precopmiles_common.ErrGetStateDB) + } + ctx := stateDB.GetContext() + // reset gas config + ctx = ctx.WithKVGasConfig(types.KVGasConfig()) + initialGas := ctx.GasMeter().GasConsumed() + + var bz []byte + switch method.Name { + // queries + case StakingFunctionValidators: + bz, err = s.Validators(ctx, evm, method, args) + case StakingFunctionValidator: + bz, err = s.Validator(ctx, evm, method, args) + case StakingFunctionValidatorDelegations: + bz, err = s.ValidatorDelegations(ctx, evm, method, args) + case StakingFunctionValidatorUnbondingDelegations: + bz, err = s.ValidatorUnbondingDelegations(ctx, evm, method, args) + case StakingFunctionDelegation: + bz, err = s.Delegation(ctx, evm, method, args) + case StakingFunctionUnbondingDelegation: + bz, err = s.UnbondingDelegation(ctx, evm, method, args) + case StakingFunctionDelegatorDelegations: + bz, err = s.DelegatorDelegations(ctx, evm, method, args) + case StakingFunctionDelegatorUnbondingDelegations: + bz, err = s.DelegatorUnbondingDelegations(ctx, evm, method, args) + case StakingFunctionRedelegations: + bz, err = s.Redelegations(ctx, evm, method, args) + case StakingFunctionDelegatorValidators: + bz, err = s.DelegatorValidators(ctx, evm, method, args) + case StakingFunctionDelegatorValidator: + bz, err = s.DelegatorValidator(ctx, evm, method, args) + case StakingFunctionPool: + bz, err = s.Pool(ctx, evm, method, args) + case StakingFunctionParams: + bz, err = s.Params(ctx, evm, method, args) + // txs + case StakingFunctionCreateValidator: + bz, err = s.CreateValidator(ctx, evm, stateDB, contract, method, args) + case StakingFunctionEditValidator: + bz, err = s.EditValidator(ctx, evm, stateDB, contract, method, args) + case StakingFunctionDelegate: + bz, err = s.Delegate(ctx, evm, stateDB, contract, method, args) + case StakingFunctionBeginRedelegate: + bz, err = s.BeginRedelegate(ctx, evm, stateDB, contract, method, args) + case StakingFunctionUndelegate: + bz, err = s.Undelegate(ctx, evm, stateDB, contract, method, args) + case StakingFunctionCancelUnbondingDelegation: + bz, err = s.CancelUnbondingDelegation(ctx, evm, stateDB, contract, method, args) + } + + if err != nil { + return nil, err + } + + cost := ctx.GasMeter().GasConsumed() - initialGas + + if !contract.UseGas(cost) { + return nil, vm.ErrOutOfGas + } + return bz, nil +} diff --git a/precompiles/staking/staking_test.go b/precompiles/staking/staking_test.go new file mode 100644 index 00000000..35a1e515 --- /dev/null +++ b/precompiles/staking/staking_test.go @@ -0,0 +1,145 @@ +package staking_test + +import ( + "errors" + "math/big" + "strings" + "testing" + + "cosmossdk.io/math" + stakingprecompile "github.com/0glabs/0g-chain/precompiles/staking" + "github.com/0glabs/0g-chain/precompiles/testutil" + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + sdk "github.com/cosmos/cosmos-sdk/types" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" + evmtypes "github.com/evmos/ethermint/x/evm/types" + "github.com/stretchr/testify/suite" +) + +type StakingTestSuite struct { + testutil.PrecompileTestSuite + + abi abi.ABI + addr common.Address + staking *stakingprecompile.StakingPrecompile + stakingKeeper *stakingkeeper.Keeper + signerOne *testutil.TestSigner + signerTwo *testutil.TestSigner +} + +func (suite *StakingTestSuite) SetupTest() { + suite.PrecompileTestSuite.SetupTest() + + suite.stakingKeeper = suite.App.GetStakingKeeper() + + suite.addr = common.HexToAddress(stakingprecompile.PrecompileAddress) + + precompiles := suite.EvmKeeper.GetPrecompiles() + precompile, ok := precompiles[suite.addr] + suite.Assert().EqualValues(ok, true) + + suite.staking = precompile.(*stakingprecompile.StakingPrecompile) + + suite.signerOne = suite.GenSigner() + suite.signerTwo = suite.GenSigner() + + abi, err := abi.JSON(strings.NewReader(stakingprecompile.StakingABI)) + suite.Assert().NoError(err) + suite.abi = abi +} + +func (suite *StakingTestSuite) AddDelegation(from string, to string, amount math.Int) { + accAddr, err := sdk.AccAddressFromHexUnsafe(from) + suite.Require().NoError(err) + valAddr, err := sdk.ValAddressFromHex(to) + suite.Require().NoError(err) + validator, found := suite.StakingKeeper.GetValidator(suite.Ctx, valAddr) + if !found { + consPriv := ed25519.GenPrivKey() + newValidator, err := stakingtypes.NewValidator(valAddr, consPriv.PubKey(), stakingtypes.Description{}) + suite.Require().NoError(err) + validator = newValidator + } + validator.Tokens = validator.Tokens.Add(amount) + validator.DelegatorShares = validator.DelegatorShares.Add(amount.ToLegacyDec()) + suite.StakingKeeper.SetValidator(suite.Ctx, validator) + bonded := suite.stakingKeeper.GetDelegatorBonded(suite.Ctx, accAddr) + suite.StakingKeeper.SetDelegation(suite.Ctx, stakingtypes.Delegation{ + DelegatorAddress: accAddr.String(), + ValidatorAddress: valAddr.String(), + Shares: bonded.Add(amount).ToLegacyDec(), + }) +} + +func (suite *StakingTestSuite) setupValidator(signer *testutil.TestSigner) { + method := stakingprecompile.StakingFunctionCreateValidator + description := stakingprecompile.Description{ + Moniker: "test node", + Identity: "test node identity", + Website: "http://test.node.com", + SecurityContact: "test node security contract", + Details: "test node details", + } + commission := stakingprecompile.CommissionRates{ + Rate: math.LegacyOneDec().BigInt(), + MaxRate: math.LegacyOneDec().BigInt(), + MaxChangeRate: math.LegacyOneDec().BigInt(), + } + minSelfDelegation := big.NewInt(1) + pubkey := "eh/aR8BGUBIYI/Ust0NVBxZafLDAm7344F9dKzZU+7g=" + value := big.NewInt(100000000) + input, err := suite.abi.Pack( + method, + description, + commission, + minSelfDelegation, + pubkey, + value, + ) + suite.Assert().NoError(err) + _, err = suite.runTx(input, signer, 10000000) + suite.Assert().NoError(err) + _, err = suite.stakingKeeper.ApplyAndReturnValidatorSetUpdates(suite.Ctx) + suite.Assert().NoError(err) +} + +func (suite *StakingTestSuite) firstBondedValidator() (sdk.ValAddress, error) { + validators := suite.stakingKeeper.GetValidators(suite.Ctx, 10) + for _, v := range validators { + if v.IsBonded() { + return sdk.ValAddressFromBech32(v.OperatorAddress) + } + } + return nil, errors.New("no bonded validator") +} + +func (suite *StakingTestSuite) runTx(input []byte, signer *testutil.TestSigner, gas uint64) ([]byte, error) { + contract := vm.NewPrecompile(vm.AccountRef(signer.Addr), vm.AccountRef(suite.addr), big.NewInt(0), gas) + contract.Input = input + + msgEthereumTx := evmtypes.NewTx(suite.EvmKeeper.ChainID(), 0, &suite.addr, big.NewInt(0), gas, big.NewInt(0), big.NewInt(0), big.NewInt(0), input, nil) + msgEthereumTx.From = signer.HexAddr + err := msgEthereumTx.Sign(suite.EthSigner, signer.Signer) + suite.Assert().NoError(err, "failed to sign Ethereum message") + + proposerAddress := suite.Ctx.BlockHeader().ProposerAddress + cfg, err := suite.EvmKeeper.EVMConfig(suite.Ctx, proposerAddress, suite.EvmKeeper.ChainID()) + suite.Assert().NoError(err, "failed to instantiate EVM config") + + msg, err := msgEthereumTx.AsMessage(suite.EthSigner, big.NewInt(0)) + suite.Assert().NoError(err, "failed to instantiate Ethereum message") + + evm := suite.EvmKeeper.NewEVM(suite.Ctx, msg, cfg, nil, suite.Statedb) + precompiles := suite.EvmKeeper.GetPrecompiles() + evm.WithPrecompiles(precompiles, []common.Address{suite.addr}) + + return suite.staking.Run(evm, contract, false) +} + +func TestKeeperSuite(t *testing.T) { + suite.Run(t, new(StakingTestSuite)) +} diff --git a/precompiles/staking/tx.go b/precompiles/staking/tx.go new file mode 100644 index 00000000..2fef1b59 --- /dev/null +++ b/precompiles/staking/tx.go @@ -0,0 +1,163 @@ +package staking + +import ( + "fmt" + "math/big" + + precopmiles_common "github.com/0glabs/0g-chain/precompiles/common" + sdk "github.com/cosmos/cosmos-sdk/types" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/evmos/ethermint/x/evm/statedb" +) + +func (s *StakingPrecompile) CreateValidator( + ctx sdk.Context, + evm *vm.EVM, + stateDB *statedb.StateDB, + contract *vm.Contract, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + msg, err := NewMsgCreateValidator(args, evm.Origin, s.stakingKeeper.BondDenom(ctx)) + if err != nil { + return nil, err + } + // validation + if contract.CallerAddress != evm.Origin { + return nil, fmt.Errorf(precopmiles_common.ErrSenderNotOrigin) + } + // execute + _, err = stakingkeeper.NewMsgServerImpl(s.stakingKeeper).CreateValidator(ctx, msg) + if err != nil { + return nil, err + } + // emit events + return method.Outputs.Pack() +} + +func (s *StakingPrecompile) EditValidator( + ctx sdk.Context, + evm *vm.EVM, + stateDB *statedb.StateDB, + contract *vm.Contract, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + msg, err := NewMsgEditValidator(args, evm.Origin) + if err != nil { + return nil, err + } + // validation + if contract.CallerAddress != evm.Origin { + return nil, fmt.Errorf(precopmiles_common.ErrSenderNotOrigin) + } + // execute + _, err = stakingkeeper.NewMsgServerImpl(s.stakingKeeper).EditValidator(ctx, msg) + if err != nil { + return nil, err + } + // emit events + return method.Outputs.Pack() +} + +func (s *StakingPrecompile) Delegate( + ctx sdk.Context, + evm *vm.EVM, + stateDB *statedb.StateDB, + contract *vm.Contract, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + msg, err := NewMsgDelegate(args, evm.Origin, s.stakingKeeper.BondDenom(ctx)) + if err != nil { + return nil, err + } + // validation + if contract.CallerAddress != evm.Origin { + return nil, fmt.Errorf(precopmiles_common.ErrSenderNotOrigin) + } + // execute + _, err = stakingkeeper.NewMsgServerImpl(s.stakingKeeper).Delegate(ctx, msg) + if err != nil { + return nil, err + } + // emit events + return method.Outputs.Pack() +} + +func (s *StakingPrecompile) BeginRedelegate( + ctx sdk.Context, + evm *vm.EVM, + stateDB *statedb.StateDB, + contract *vm.Contract, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + msg, err := NewMsgBeginRedelegate(args, evm.Origin, s.stakingKeeper.BondDenom(ctx)) + if err != nil { + return nil, err + } + // validation + if contract.CallerAddress != evm.Origin { + return nil, fmt.Errorf(precopmiles_common.ErrSenderNotOrigin) + } + // execute + response, err := stakingkeeper.NewMsgServerImpl(s.stakingKeeper).BeginRedelegate(ctx, msg) + if err != nil { + return nil, err + } + // emit events + return method.Outputs.Pack(big.NewInt(response.CompletionTime.UTC().Unix())) +} + +func (s *StakingPrecompile) Undelegate( + ctx sdk.Context, + evm *vm.EVM, + stateDB *statedb.StateDB, + contract *vm.Contract, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + msg, err := NewMsgUndelegate(args, evm.Origin, s.stakingKeeper.BondDenom(ctx)) + if err != nil { + return nil, err + } + // validation + if contract.CallerAddress != evm.Origin { + return nil, fmt.Errorf(precopmiles_common.ErrSenderNotOrigin) + } + // execute + response, err := stakingkeeper.NewMsgServerImpl(s.stakingKeeper).Undelegate(ctx, msg) + if err != nil { + return nil, err + } + // emit events + return method.Outputs.Pack(big.NewInt(response.CompletionTime.UTC().Unix())) +} + +func (s *StakingPrecompile) CancelUnbondingDelegation( + ctx sdk.Context, + evm *vm.EVM, + stateDB *statedb.StateDB, + contract *vm.Contract, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + msg, err := NewMsgCancelUnbondingDelegation(args, evm.Origin, s.stakingKeeper.BondDenom(ctx)) + if err != nil { + return nil, err + } + // validation + if contract.CallerAddress != evm.Origin { + return nil, fmt.Errorf(precopmiles_common.ErrSenderNotOrigin) + } + // execute + _, err = stakingkeeper.NewMsgServerImpl(s.stakingKeeper).CancelUnbondingDelegation(ctx, msg) + if err != nil { + return nil, err + } + // emit events + return method.Outputs.Pack() +} diff --git a/precompiles/staking/tx_test.go b/precompiles/staking/tx_test.go new file mode 100644 index 00000000..baab8f03 --- /dev/null +++ b/precompiles/staking/tx_test.go @@ -0,0 +1,485 @@ +package staking_test + +import ( + "encoding/base64" + "math/big" + "time" + + "cosmossdk.io/math" + stakingprecompile "github.com/0glabs/0g-chain/precompiles/staking" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/common" + "github.com/evmos/ethermint/x/evm/statedb" +) + +func (s *StakingTestSuite) TestCreateValidator() { + method := stakingprecompile.StakingFunctionCreateValidator + description := stakingprecompile.Description{ + Moniker: "test node", + Identity: "test node identity", + Website: "http://test.node.com", + SecurityContact: "test node security contract", + Details: "test node details", + } + commission := stakingprecompile.CommissionRates{ + Rate: math.LegacyOneDec().BigInt(), + MaxRate: math.LegacyOneDec().BigInt(), + MaxChangeRate: math.LegacyOneDec().BigInt(), + } + minSelfDelegation := big.NewInt(1) + pubkey := "eh/aR8BGUBIYI/Ust0NVBxZafLDAm7344F9dKzZU+7g=" + value := big.NewInt(100000000) + + testCases := []struct { + name string + malleate func() []byte + gas uint64 + callerAddress *common.Address + postCheck func(data []byte) + expError bool + errContains string + }{ + { + "fail - ErrPubKeyInvalidLength", + func() []byte { + input, err := s.abi.Pack( + method, + description, + commission, + minSelfDelegation, + s.signerOne.HexAddr, + value, + ) + s.Assert().NoError(err) + return input + }, + 200000, + nil, + func([]byte) {}, + true, + stakingprecompile.ErrPubKeyInvalidLength, + }, + { + "success", + func() []byte { + input, err := s.abi.Pack( + method, + description, + commission, + minSelfDelegation, + pubkey, + value, + ) + s.Assert().NoError(err) + return input + }, + 200000, + nil, + func(data []byte) {}, + false, + "", + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + s.SetupTest() + + bz, err := s.runTx(tc.malleate(), s.signerOne, 10000000) + s.stakingKeeper.ApplyAndReturnValidatorSetUpdates(s.Ctx) + + if tc.expError { + s.Require().ErrorContains(err, tc.errContains) + s.Require().Empty(bz) + } else { + s.Require().NoError(err) + // query the validator in the staking keeper + validator := s.StakingKeeper.Validator(s.Ctx, s.signerOne.ValAddr) + s.Require().NoError(err) + + s.Require().NotNil(validator, "expected validator not to be nil") + tc.postCheck(bz) + + isBonded := validator.IsBonded() + s.Require().Equal(true, isBonded, "expected validator bonded to be %t; got %t", true, isBonded) + + consPubKey, err := validator.ConsPubKey() + s.Require().NoError(err) + consPubKeyBase64 := base64.StdEncoding.EncodeToString(consPubKey.Bytes()) + s.Require().Equal(pubkey, consPubKeyBase64, "expected validator pubkey to be %s; got %s", pubkey, consPubKeyBase64) + + operator := validator.GetOperator() + s.Require().Equal(s.signerOne.ValAddr, operator, "expected validator operator to be %s; got %s", s.signerOne.ValAddr, operator) + + commissionRate := validator.GetCommission() + s.Require().Equal(commission.Rate.String(), commissionRate.BigInt().String(), "expected validator commission rate to be %s; got %s", commission.Rate.String(), commissionRate.String()) + + valMinSelfDelegation := validator.GetMinSelfDelegation() + s.Require().Equal(minSelfDelegation.String(), valMinSelfDelegation.String(), "expected validator min self delegation to be %s; got %s", minSelfDelegation.String(), valMinSelfDelegation.String()) + + moniker := validator.GetMoniker() + s.Require().Equal(description.Moniker, moniker, "expected validator moniker to be %s; got %s", description.Moniker, moniker) + + jailed := validator.IsJailed() + s.Require().Equal(false, jailed, "expected validator jailed to be %t; got %t", false, jailed) + } + }) + } +} + +func (s *StakingTestSuite) TestEditValidator() { + method := stakingprecompile.StakingFunctionEditValidator + description := stakingprecompile.Description{ + Moniker: "test node", + Identity: "test node identity", + Website: "http://test.node.com", + SecurityContact: "test node security contract", + Details: "test node details", + } + newRate := math.LegacyOneDec().BigInt() + newRate.Div(newRate, big.NewInt(2)) + minSelfDelegation := big.NewInt(2) + + testCases := []struct { + name string + malleate func() []byte + gas uint64 + callerAddress *common.Address + postCheck func(data []byte) + expError bool + errContains string + }{ + { + "success", + func() []byte { + input, err := s.abi.Pack( + method, + description, + stakingprecompile.NullableUint{ + IsNull: false, + Value: newRate, + }, + stakingprecompile.NullableUint{ + IsNull: true, + Value: math.LegacyOneDec().BigInt(), + }, + ) + s.Assert().NoError(err) + return input + }, + 200000, + nil, + func(data []byte) {}, + false, + "", + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + s.SetupTest() + s.setupValidator(s.signerOne) + // move block time forward + s.Ctx = s.Ctx.WithBlockTime(time.Now().Add(time.Hour * 100)) + s.Statedb = statedb.New(s.Ctx, s.EvmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(s.Ctx.HeaderHash().Bytes()))) + + bz, err := s.runTx(tc.malleate(), s.signerOne, 10000000) + + if tc.expError { + s.Require().ErrorContains(err, tc.errContains) + s.Require().Empty(bz) + } else { + s.Require().NoError(err) + // query the validator in the staking keeper + validator := s.StakingKeeper.Validator(s.Ctx, s.signerOne.ValAddr) + s.Require().NoError(err) + + s.Require().NotNil(validator, "expected validator not to be nil") + tc.postCheck(bz) + + isBonded := validator.IsBonded() + s.Require().Equal(true, isBonded, "expected validator bonded to be %t; got %t", false, isBonded) + + operator := validator.GetOperator() + s.Require().Equal(s.signerOne.ValAddr, operator, "expected validator operator to be %s; got %s", s.signerOne.ValAddr, operator) + + commissionRate := validator.GetCommission() + s.Require().Equal(newRate.String(), commissionRate.BigInt().String(), "expected validator commission rate to be %s; got %s", newRate.String(), commissionRate.String()) + + valMinSelfDelegation := validator.GetMinSelfDelegation() + s.Require().Equal(big.NewInt(1).String(), valMinSelfDelegation.String(), "expected validator min self delegation to be %s; got %s", minSelfDelegation.String(), valMinSelfDelegation.String()) + + moniker := validator.GetMoniker() + s.Require().Equal(description.Moniker, moniker, "expected validator moniker to be %s; got %s", description.Moniker, moniker) + + jailed := validator.IsJailed() + s.Require().Equal(false, jailed, "expected validator jailed to be %t; got %t", false, jailed) + } + }) + } +} + +func (s *StakingTestSuite) TestDelegate() { + method := stakingprecompile.StakingFunctionDelegate + + testCases := []struct { + name string + malleate func(valAddr string) []byte + gas uint64 + callerAddress *common.Address + postCheck func(valAddr sdk.ValAddress) + expError bool + errContains string + }{ + { + "success", + func(valAddr string) []byte { + input, err := s.abi.Pack( + method, + valAddr, + big.NewInt(1000000), + ) + s.Assert().NoError(err) + return input + }, + 200000, + nil, + func(valAddr sdk.ValAddress) { + d, found := s.stakingKeeper.GetDelegation(s.Ctx, s.signerOne.AccAddr, valAddr) + s.Assert().EqualValues(found, true) + s.Assert().EqualValues(d.ValidatorAddress, valAddr.String()) + s.Assert().EqualValues(d.DelegatorAddress, s.signerOne.AccAddr.String()) + + // jsonData, _ := json.MarshalIndent(d, "", " ") + // fmt.Printf("delegation: %s\n", string(jsonData)) + }, + false, + "", + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + s.SetupTest() + + operatorAddress, err := s.firstBondedValidator() + s.Require().NoError(err) + + bz, err := s.runTx(tc.malleate(operatorAddress.String()), s.signerOne, 10000000) + + if tc.expError { + s.Require().ErrorContains(err, tc.errContains) + s.Require().Empty(bz) + } else { + s.Require().NoError(err) + tc.postCheck(operatorAddress) + } + }) + } +} + +func (s *StakingTestSuite) TestBeginRedelegate() { + method := stakingprecompile.StakingFunctionBeginRedelegate + + testCases := []struct { + name string + malleate func(srcAddr, dstAddr string) []byte + gas uint64 + callerAddress *common.Address + postCheck func(data []byte, srcAddr, dstAddr sdk.ValAddress) + expError bool + errContains string + }{ + { + "success", + func(srcAddr, dstAddr string) []byte { + input, err := s.abi.Pack( + method, + srcAddr, + dstAddr, + big.NewInt(1000000), + ) + s.Assert().NoError(err) + return input + }, + 200000, + nil, + func(data []byte, srcAddr, dstAddr sdk.ValAddress) { + out, err := s.abi.Methods[method].Outputs.Unpack(data) + s.Require().NoError(err, "failed to unpack output") + + d, found := s.stakingKeeper.GetRedelegation(s.Ctx, s.signerOne.AccAddr, srcAddr, dstAddr) + s.Assert().EqualValues(found, true) + s.Assert().EqualValues(d.DelegatorAddress, s.signerOne.AccAddr.String()) + s.Assert().EqualValues(d.ValidatorSrcAddress, srcAddr.String()) + s.Assert().EqualValues(d.ValidatorDstAddress, dstAddr.String()) + + completionTime := out[0].(*big.Int) + params := s.stakingKeeper.GetParams(s.Ctx) + s.Assert().EqualValues(completionTime.Int64(), s.Ctx.BlockHeader().Time.Add(params.UnbondingTime).UTC().Unix()) + // jsonData, _ := json.MarshalIndent(d, "", " ") + // fmt.Printf("redelegation: %s\n", string(jsonData)) + }, + false, + "", + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + s.SetupTest() + operatorAddress, err := s.firstBondedValidator() + s.Require().NoError(err) + + // move block time forward + s.Ctx = s.Ctx.WithBlockTime(time.Now().Add(time.Hour * 100)) + s.Statedb = statedb.New(s.Ctx, s.EvmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(s.Ctx.HeaderHash().Bytes()))) + + s.setupValidator(s.signerOne) + + bz, err := s.runTx(tc.malleate(s.signerOne.ValAddr.String(), operatorAddress.String()), s.signerOne, 10000000) + + if tc.expError { + s.Require().ErrorContains(err, tc.errContains) + s.Require().Empty(bz) + } else { + s.Require().NoError(err) + tc.postCheck(bz, s.signerOne.ValAddr, operatorAddress) + } + }) + } +} + +func (s *StakingTestSuite) TestUndelegate() { + method := stakingprecompile.StakingFunctionUndelegate + + testCases := []struct { + name string + malleate func(valAddr string) []byte + gas uint64 + callerAddress *common.Address + postCheck func(data []byte, valAddr sdk.ValAddress) + expError bool + errContains string + }{ + { + "success", + func(valAddr string) []byte { + input, err := s.abi.Pack( + method, + valAddr, + big.NewInt(1000000), + ) + s.Assert().NoError(err) + return input + }, + 200000, + nil, + func(data []byte, valAddr sdk.ValAddress) { + out, err := s.abi.Methods[method].Outputs.Unpack(data) + s.Require().NoError(err, "failed to unpack output") + + d, found := s.stakingKeeper.GetUnbondingDelegation(s.Ctx, s.signerOne.AccAddr, valAddr) + s.Assert().EqualValues(found, true) + s.Assert().EqualValues(d.DelegatorAddress, s.signerOne.AccAddr.String()) + s.Assert().EqualValues(d.ValidatorAddress, valAddr.String()) + + completionTime := out[0].(*big.Int) + params := s.stakingKeeper.GetParams(s.Ctx) + s.Assert().EqualValues(completionTime.Int64(), s.Ctx.BlockHeader().Time.Add(params.UnbondingTime).UTC().Unix()) + // jsonData, _ := json.MarshalIndent(d, "", " ") + // fmt.Printf("redelegation: %s\n", string(jsonData)) + }, + false, + "", + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + s.SetupTest() + + // move block time forward + s.Ctx = s.Ctx.WithBlockTime(time.Now().Add(time.Hour * 100)) + s.Statedb = statedb.New(s.Ctx, s.EvmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(s.Ctx.HeaderHash().Bytes()))) + + s.setupValidator(s.signerOne) + + bz, err := s.runTx(tc.malleate(s.signerOne.ValAddr.String()), s.signerOne, 10000000) + + if tc.expError { + s.Require().ErrorContains(err, tc.errContains) + s.Require().Empty(bz) + } else { + s.Require().NoError(err) + tc.postCheck(bz, s.signerOne.ValAddr) + } + }) + } +} + +func (s *StakingTestSuite) TestCancelUnbondingDelegation() { + method := stakingprecompile.StakingFunctionCancelUnbondingDelegation + + testCases := []struct { + name string + malleate func(valAddr string, height *big.Int) []byte + gas uint64 + callerAddress *common.Address + postCheck func(valAddr sdk.ValAddress) + expError bool + errContains string + }{ + { + "success", + func(valAddr string, height *big.Int) []byte { + input, err := s.abi.Pack( + method, + valAddr, + big.NewInt(1), + height, + ) + s.Assert().NoError(err) + return input + }, + 200000, + nil, + func(valAddr sdk.ValAddress) { + _, found := s.stakingKeeper.GetUnbondingDelegation(s.Ctx, s.signerOne.AccAddr, valAddr) + s.Assert().EqualValues(found, false) + // jsonData, _ := json.MarshalIndent(d, "", " ") + // fmt.Printf("redelegation: %s\n", string(jsonData)) + }, + false, + "", + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + s.SetupTest() + + // move block time forward + s.Ctx = s.Ctx.WithBlockTime(time.Now().Add(time.Hour * 100)) + s.Statedb = statedb.New(s.Ctx, s.EvmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(s.Ctx.HeaderHash().Bytes()))) + + s.setupValidator(s.signerOne) + // unbond + _, err := s.stakingKeeper.Undelegate(s.Ctx, s.signerOne.AccAddr, s.signerOne.ValAddr, sdk.NewDec(1)) + s.Require().NoError(err) + + u, _ := s.stakingKeeper.GetUnbondingDelegation(s.Ctx, s.signerOne.AccAddr, s.signerOne.ValAddr) + height := u.Entries[0].CreationHeight + + bz, err := s.runTx(tc.malleate(s.signerOne.ValAddr.String(), big.NewInt(height)), s.signerOne, 10000000) + + if tc.expError { + s.Require().ErrorContains(err, tc.errContains) + s.Require().Empty(bz) + } else { + s.Require().NoError(err) + tc.postCheck(s.signerOne.ValAddr) + } + }) + } +} diff --git a/precompiles/staking/types.go b/precompiles/staking/types.go new file mode 100644 index 00000000..433f95d7 --- /dev/null +++ b/precompiles/staking/types.go @@ -0,0 +1,602 @@ +package staking + +import ( + "encoding/base64" + "errors" + "fmt" + "math/big" + + "cosmossdk.io/math" + precopmiles_common "github.com/0glabs/0g-chain/precompiles/common" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" + query "github.com/cosmos/cosmos-sdk/types/query" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/ethereum/go-ethereum/common" +) + +type Commission = struct { + CommissionRates CommissionRates `json:"commissionRates"` + UpdateTime *big.Int `json:"updateTime"` +} + +type CommissionRates = struct { + Rate *big.Int `json:"rate"` + MaxRate *big.Int `json:"maxRate"` + MaxChangeRate *big.Int `json:"maxChangeRate"` +} + +type Delegation = struct { + DelegatorAddress string `json:"delegatorAddress"` + ValidatorAddress string `json:"validatorAddress"` + Shares *big.Int `json:"shares"` +} + +type DelegationResponse = struct { + Delegation Delegation `json:"delegation"` + Balance *big.Int `json:"balance"` +} + +type Description = struct { + Moniker string `json:"moniker"` + Identity string `json:"identity"` + Website string `json:"website"` + SecurityContact string `json:"securityContact"` + Details string `json:"details"` +} + +type NullableUint = struct { + IsNull bool `json:"isNull"` + Value *big.Int `json:"value"` +} + +type PageRequest = struct { + Key []byte `json:"key"` + Offset uint64 `json:"offset"` + Limit uint64 `json:"limit"` + CountTotal bool `json:"countTotal"` + Reverse bool `json:"reverse"` +} + +type PageResponse = struct { + NextKey []byte `json:"nextKey"` + Total uint64 `json:"total"` +} + +type Params = struct { + UnbondingTime int64 `json:"unbondingTime"` + MaxValidators uint32 `json:"maxValidators"` + MaxEntries uint32 `json:"maxEntries"` + HistoricalEntries uint32 `json:"historicalEntries"` + BondDenom string `json:"bondDenom"` + MinCommissionRate *big.Int `json:"minCommissionRate"` +} + +type Redelegation = struct { + DelegatorAddress string `json:"delegatorAddress"` + ValidatorSrcAddress string `json:"validatorSrcAddress"` + ValidatorDstAddress string `json:"validatorDstAddress"` + Entries []RedelegationEntry `json:"entries"` +} + +type RedelegationEntry = struct { + CreationHeight int64 `json:"creationHeight"` + CompletionTime int64 `json:"completionTime"` + InitialBalance *big.Int `json:"initialBalance"` + SharesDst *big.Int `json:"sharesDst"` + UnbondingId uint64 `json:"unbondingId"` + UnbondingOnHoldRefCount int64 `json:"unbondingOnHoldRefCount"` +} + +type RedelegationEntryResponse = struct { + RedelegationEntry RedelegationEntry `json:"redelegationEntry"` + Balance *big.Int `json:"balance"` +} + +type RedelegationResponse = struct { + Redelegation Redelegation `json:"redelegation"` + Entries []RedelegationEntryResponse `json:"entries"` +} + +type UnbondingDelegation = struct { + DelegatorAddress string `json:"delegatorAddress"` + ValidatorAddress string `json:"validatorAddress"` + Entries []UnbondingDelegationEntry `json:"entries"` +} + +type UnbondingDelegationEntry = struct { + CreationHeight int64 `json:"creationHeight"` + CompletionTime int64 `json:"completionTime"` + InitialBalance *big.Int `json:"initialBalance"` + Balance *big.Int `json:"balance"` + UnbondingId uint64 `json:"unbondingId"` + UnbondingOnHoldRefCount int64 `json:"unbondingOnHoldRefCount"` +} + +type Validator = struct { + OperatorAddress string `json:"operatorAddress"` + ConsensusPubkey string `json:"consensusPubkey"` + Jailed bool `json:"jailed"` + Status uint8 `json:"status"` + Tokens *big.Int `json:"tokens"` + DelegatorShares *big.Int `json:"delegatorShares"` + Description Description `json:"description"` + UnbondingHeight int64 `json:"unbondingHeight"` + UnbondingTime int64 `json:"unbondingTime"` + Commission Commission `json:"commission"` + MinSelfDelegation *big.Int `json:"minSelfDelegation"` + UnbondingOnHoldRefCount int64 `json:"unbondingOnHoldRefCount"` + UnbondingIds []uint64 `json:"unbondingIds"` +} + +func convertValidator(v stakingtypes.Validator) Validator { + validator := Validator{} + operatorAddress, err := sdk.ValAddressFromBech32(v.OperatorAddress) + if err != nil { + validator.OperatorAddress = v.OperatorAddress + } else { + validator.OperatorAddress = common.BytesToAddress(operatorAddress.Bytes()).String() + } + + ed25519pk, ok := v.ConsensusPubkey.GetCachedValue().(cryptotypes.PubKey) + if !ok { + validator.ConsensusPubkey = v.ConsensusPubkey.String() + } else { + validator.ConsensusPubkey = base64.StdEncoding.EncodeToString(ed25519pk.Bytes()) + } + + validator.Jailed = v.Jailed + validator.Status = uint8(v.Status) + validator.Tokens = v.Tokens.BigInt() + validator.DelegatorShares = v.DelegatorShares.BigInt() + validator.Description = Description{ + Moniker: v.Description.Moniker, + Identity: v.Description.Identity, + Website: v.Description.Website, + SecurityContact: v.Description.SecurityContact, + Details: v.Description.Details, + } + validator.UnbondingHeight = v.UnbondingHeight + validator.UnbondingTime = v.UnbondingTime.UTC().Unix() + validator.Commission = Commission{ + CommissionRates: convertCommissionRates(v.Commission.CommissionRates), + UpdateTime: big.NewInt(v.Commission.UpdateTime.UTC().Unix()), + } + validator.MinSelfDelegation = v.MinSelfDelegation.BigInt() + validator.UnbondingOnHoldRefCount = v.UnbondingOnHoldRefCount + validator.UnbondingIds = v.UnbondingIds + return validator +} + +func convertQueryPageRequest(pagination PageRequest) *query.PageRequest { + return &query.PageRequest{ + Key: pagination.Key, + Offset: pagination.Offset, + Limit: pagination.Limit, + CountTotal: pagination.CountTotal, + Reverse: pagination.Reverse, + } +} + +func convertPageResponse(pagination *query.PageResponse) PageResponse { + if pagination == nil { + return PageResponse{ + NextKey: make([]byte, 0), + Total: 1, + } + } + return PageResponse{ + NextKey: pagination.NextKey, + Total: pagination.Total, + } +} + +func convertStakingDescription(description Description) stakingtypes.Description { + return stakingtypes.Description{ + Moniker: description.Moniker, + Identity: description.Identity, + Website: description.Website, + SecurityContact: description.SecurityContact, + Details: description.Details, + } +} + +func convertStakingCommissionRates(commission CommissionRates) stakingtypes.CommissionRates { + return stakingtypes.CommissionRates{ + Rate: precopmiles_common.BigIntToLegacyDec(commission.Rate), + MaxRate: precopmiles_common.BigIntToLegacyDec(commission.MaxRate), + MaxChangeRate: precopmiles_common.BigIntToLegacyDec(commission.MaxChangeRate), + } +} + +func convertCommissionRates(commission stakingtypes.CommissionRates) CommissionRates { + return CommissionRates{ + Rate: commission.Rate.BigInt(), + MaxRate: commission.MaxRate.BigInt(), + MaxChangeRate: commission.MaxChangeRate.BigInt(), + } +} + +func convertDelegation(delegation stakingtypes.Delegation) Delegation { + return Delegation{ + DelegatorAddress: delegation.DelegatorAddress, + ValidatorAddress: delegation.ValidatorAddress, + Shares: delegation.Shares.BigInt(), + } +} + +func convertDelegationResponse(response stakingtypes.DelegationResponse) DelegationResponse { + return DelegationResponse{ + Delegation: convertDelegation(response.Delegation), + Balance: response.Balance.Amount.BigInt(), + } +} + +func convertUnbondingDelegationEntry(entry stakingtypes.UnbondingDelegationEntry) UnbondingDelegationEntry { + return UnbondingDelegationEntry{ + CreationHeight: entry.CreationHeight, + CompletionTime: entry.CompletionTime.UTC().Unix(), + InitialBalance: entry.InitialBalance.BigInt(), + Balance: entry.Balance.BigInt(), + UnbondingId: entry.UnbondingId, + UnbondingOnHoldRefCount: entry.UnbondingOnHoldRefCount, + } +} + +func convertUnbondingDelegation(response stakingtypes.UnbondingDelegation) UnbondingDelegation { + entries := make([]UnbondingDelegationEntry, len(response.Entries)) + for i, v := range response.Entries { + entries[i] = convertUnbondingDelegationEntry(v) + } + return UnbondingDelegation{ + DelegatorAddress: response.DelegatorAddress, + ValidatorAddress: response.ValidatorAddress, + Entries: entries, + } +} + +func convertRedelegationEntry(entry stakingtypes.RedelegationEntry) RedelegationEntry { + return RedelegationEntry{ + CreationHeight: entry.CreationHeight, + CompletionTime: entry.CompletionTime.UTC().Unix(), + InitialBalance: entry.InitialBalance.BigInt(), + SharesDst: entry.SharesDst.BigInt(), + UnbondingId: entry.UnbondingId, + UnbondingOnHoldRefCount: entry.UnbondingOnHoldRefCount, + } +} + +func convertRedelegation(redelegation stakingtypes.Redelegation) Redelegation { + entries := make([]RedelegationEntry, len(redelegation.Entries)) + for i, v := range redelegation.Entries { + entries[i] = convertRedelegationEntry(v) + } + return Redelegation{ + DelegatorAddress: redelegation.DelegatorAddress, + ValidatorSrcAddress: redelegation.ValidatorSrcAddress, + ValidatorDstAddress: redelegation.ValidatorDstAddress, + Entries: entries, + } +} + +func convertRedelegationEntryResponse(response stakingtypes.RedelegationEntryResponse) RedelegationEntryResponse { + return RedelegationEntryResponse{ + RedelegationEntry: convertRedelegationEntry(response.RedelegationEntry), + Balance: response.Balance.BigInt(), + } +} + +func convertRedelegationResponse(response stakingtypes.RedelegationResponse) RedelegationResponse { + entries := make([]RedelegationEntryResponse, len(response.Entries)) + for i, v := range response.Entries { + entries[i] = convertRedelegationEntryResponse(v) + } + return RedelegationResponse{ + Redelegation: convertRedelegation(response.Redelegation), + Entries: entries, + } +} + +func convertParams(params stakingtypes.Params) Params { + return Params{ + UnbondingTime: int64(params.UnbondingTime.Seconds()), + MaxValidators: params.MaxValidators, + MaxEntries: params.MaxEntries, + HistoricalEntries: params.HistoricalEntries, + BondDenom: params.BondDenom, + MinCommissionRate: params.MinCommissionRate.BigInt(), + } +} + +func NewMsgCreateValidator(args []interface{}, sender common.Address, denom string) (*stakingtypes.MsgCreateValidator, error) { + if len(args) != 5 { + return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 5, len(args)) + } + description := args[0].(Description) + commission := args[1].(CommissionRates) + minSelfDelegation := args[2].(*big.Int) + + pkstr := args[3].(string) + bz, err := base64.StdEncoding.DecodeString(pkstr) + if err != nil { + return nil, err + } + var pk cryptotypes.PubKey + if len(bz) == ed25519.PubKeySize { + pk = &ed25519.PubKey{Key: bz} + } else { + return nil, errors.New(ErrPubKeyInvalidLength) + } + pkAny, err := codectypes.NewAnyWithValue(pk) + if err != nil { + return nil, err + } + + value := args[4].(*big.Int) + msg := &stakingtypes.MsgCreateValidator{ + Description: convertStakingDescription(description), + Commission: convertStakingCommissionRates(commission), + MinSelfDelegation: math.NewIntFromBigInt(minSelfDelegation), + DelegatorAddress: sdk.AccAddress(sender.Bytes()).String(), + ValidatorAddress: sdk.ValAddress(sender.Bytes()).String(), + Pubkey: pkAny, + Value: sdk.Coin{Denom: denom, Amount: math.NewIntFromBigInt(value)}, + } + return msg, msg.ValidateBasic() +} + +func NewMsgEditValidator(args []interface{}, sender common.Address) (*stakingtypes.MsgEditValidator, error) { + if len(args) != 3 { + return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 3, len(args)) + } + description := args[0].(Description) + + commissionRateNullable := args[1].(NullableUint) + var commissionRate *sdk.Dec + if !commissionRateNullable.IsNull { + value := precopmiles_common.BigIntToLegacyDec(commissionRateNullable.Value) + commissionRate = &value + } + + minSelfDelegationNullable := args[2].(NullableUint) + var minSelfDelegation *sdk.Int + if !minSelfDelegationNullable.IsNull { + value := math.NewIntFromBigInt(minSelfDelegationNullable.Value) + minSelfDelegation = &value + } + + msg := &stakingtypes.MsgEditValidator{ + Description: convertStakingDescription(description), + CommissionRate: commissionRate, + ValidatorAddress: sdk.ValAddress(sender.Bytes()).String(), + MinSelfDelegation: minSelfDelegation, + } + return msg, msg.ValidateBasic() +} + +func NewMsgDelegate(args []interface{}, sender common.Address, denom string) (*stakingtypes.MsgDelegate, error) { + if len(args) != 2 { + return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args)) + } + validatorAddress := args[0].(string) + amount := args[1].(*big.Int) + + msg := &stakingtypes.MsgDelegate{ + DelegatorAddress: sdk.AccAddress(sender.Bytes()).String(), + ValidatorAddress: validatorAddress, + Amount: sdk.Coin{Denom: denom, Amount: math.NewIntFromBigInt(amount)}, + } + return msg, msg.ValidateBasic() +} + +func NewMsgBeginRedelegate(args []interface{}, sender common.Address, denom string) (*stakingtypes.MsgBeginRedelegate, error) { + if len(args) != 3 { + return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 3, len(args)) + } + validatorSrcAddress := args[0].(string) + validatorDstAddress := args[1].(string) + amount := args[2].(*big.Int) + + msg := &stakingtypes.MsgBeginRedelegate{ + DelegatorAddress: sdk.AccAddress(sender.Bytes()).String(), + ValidatorSrcAddress: validatorSrcAddress, + ValidatorDstAddress: validatorDstAddress, + Amount: sdk.Coin{Denom: denom, Amount: math.NewIntFromBigInt(amount)}, + } + return msg, msg.ValidateBasic() +} + +func NewMsgUndelegate(args []interface{}, sender common.Address, denom string) (*stakingtypes.MsgUndelegate, error) { + if len(args) != 2 { + return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args)) + } + validatorAddress := args[0].(string) + amount := args[1].(*big.Int) + + msg := &stakingtypes.MsgUndelegate{ + DelegatorAddress: sdk.AccAddress(sender.Bytes()).String(), + ValidatorAddress: validatorAddress, + Amount: sdk.Coin{Denom: denom, Amount: math.NewIntFromBigInt(amount)}, + } + return msg, msg.ValidateBasic() +} + +func NewMsgCancelUnbondingDelegation(args []interface{}, sender common.Address, denom string) (*stakingtypes.MsgCancelUnbondingDelegation, error) { + if len(args) != 3 { + return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 3, len(args)) + } + validatorAddress := args[0].(string) + amount := args[1].(*big.Int) + creationHeight := args[2].(*big.Int) + + msg := &stakingtypes.MsgCancelUnbondingDelegation{ + DelegatorAddress: sdk.AccAddress(sender.Bytes()).String(), + ValidatorAddress: validatorAddress, + Amount: sdk.Coin{Denom: denom, Amount: math.NewIntFromBigInt(amount)}, + CreationHeight: creationHeight.Int64(), + } + return msg, msg.ValidateBasic() +} + +func NewQueryValidatorsRequest(args []interface{}) (*stakingtypes.QueryValidatorsRequest, error) { + if len(args) != 2 { + return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args)) + } + status := args[0].(string) + pagination := args[1].(PageRequest) + + return &stakingtypes.QueryValidatorsRequest{ + Status: status, + Pagination: convertQueryPageRequest(pagination), + }, nil +} + +func NewQueryValidatorRequest(args []interface{}) (*stakingtypes.QueryValidatorRequest, error) { + if len(args) != 1 { + return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 1, len(args)) + } + validatorAddress := args[0].(string) + + return &stakingtypes.QueryValidatorRequest{ + ValidatorAddr: validatorAddress, + }, nil +} + +func NewQueryValidatorDelegationsRequest(args []interface{}) (*stakingtypes.QueryValidatorDelegationsRequest, error) { + if len(args) != 2 { + return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args)) + } + validatorAddr := args[0].(string) + pagination := args[1].(PageRequest) + + return &stakingtypes.QueryValidatorDelegationsRequest{ + ValidatorAddr: validatorAddr, + Pagination: convertQueryPageRequest(pagination), + }, nil +} + +func NewQueryValidatorUnbondingDelegationsRequest(args []interface{}) (*stakingtypes.QueryValidatorUnbondingDelegationsRequest, error) { + if len(args) != 2 { + return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args)) + } + validatorAddr := args[0].(string) + pagination := args[1].(PageRequest) + + return &stakingtypes.QueryValidatorUnbondingDelegationsRequest{ + ValidatorAddr: validatorAddr, + Pagination: convertQueryPageRequest(pagination), + }, nil +} + +func NewQueryDelegationRequest(args []interface{}) (*stakingtypes.QueryDelegationRequest, error) { + if len(args) != 2 { + return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args)) + } + delegatorAddr := args[0].(string) + validatorAddr := args[1].(string) + + return &stakingtypes.QueryDelegationRequest{ + DelegatorAddr: delegatorAddr, + ValidatorAddr: validatorAddr, + }, nil +} + +func NewQueryUnbondingDelegationRequest(args []interface{}) (*stakingtypes.QueryUnbondingDelegationRequest, error) { + if len(args) != 2 { + return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args)) + } + delegatorAddr := args[0].(string) + validatorAddr := args[1].(string) + + return &stakingtypes.QueryUnbondingDelegationRequest{ + DelegatorAddr: delegatorAddr, + ValidatorAddr: validatorAddr, + }, nil +} + +func NewQueryDelegatorDelegationsRequest(args []interface{}) (*stakingtypes.QueryDelegatorDelegationsRequest, error) { + if len(args) != 2 { + return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args)) + } + delegatorAddr := args[0].(string) + pagination := args[1].(PageRequest) + + return &stakingtypes.QueryDelegatorDelegationsRequest{ + DelegatorAddr: delegatorAddr, + Pagination: convertQueryPageRequest(pagination), + }, nil +} + +func NewQueryDelegatorUnbondingDelegationsRequest(args []interface{}) (*stakingtypes.QueryDelegatorUnbondingDelegationsRequest, error) { + if len(args) != 2 { + return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args)) + } + delegatorAddr := args[0].(string) + pagination := args[1].(PageRequest) + + return &stakingtypes.QueryDelegatorUnbondingDelegationsRequest{ + DelegatorAddr: delegatorAddr, + Pagination: convertQueryPageRequest(pagination), + }, nil +} + +func NewQueryRedelegationsRequest(args []interface{}) (*stakingtypes.QueryRedelegationsRequest, error) { + if len(args) != 4 { + return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 4, len(args)) + } + delegatorAddress := args[0].(string) + validatorSrcAddress := args[1].(string) + validatorDstAddress := args[2].(string) + pagination := args[3].(PageRequest) + + return &stakingtypes.QueryRedelegationsRequest{ + DelegatorAddr: delegatorAddress, + SrcValidatorAddr: validatorSrcAddress, + DstValidatorAddr: validatorDstAddress, + Pagination: convertQueryPageRequest(pagination), + }, nil +} + +func NewQueryDelegatorValidatorsRequest(args []interface{}) (*stakingtypes.QueryDelegatorValidatorsRequest, error) { + if len(args) != 2 { + return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args)) + } + delegatorAddr := args[0].(string) + pagination := args[1].(PageRequest) + + return &stakingtypes.QueryDelegatorValidatorsRequest{ + DelegatorAddr: delegatorAddr, + Pagination: convertQueryPageRequest(pagination), + }, nil +} + +func NewQueryDelegatorValidatorRequest(args []interface{}) (*stakingtypes.QueryDelegatorValidatorRequest, error) { + if len(args) != 2 { + return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args)) + } + delegatorAddr := args[0].(string) + validatorAddr := args[1].(string) + + return &stakingtypes.QueryDelegatorValidatorRequest{ + DelegatorAddr: delegatorAddr, + ValidatorAddr: validatorAddr, + }, nil +} + +func NewQueryPoolRequest(args []interface{}) (*stakingtypes.QueryPoolRequest, error) { + if len(args) != 0 { + return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 0, len(args)) + } + + return &stakingtypes.QueryPoolRequest{}, nil +} + +func NewQueryParamsRequest(args []interface{}) (*stakingtypes.QueryParamsRequest, error) { + if len(args) != 0 { + return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 0, len(args)) + } + + return &stakingtypes.QueryParamsRequest{}, nil +} diff --git a/precompiles/testutil/suite.go b/precompiles/testutil/suite.go index 1b6a9ce3..ffeabb52 100644 --- a/precompiles/testutil/suite.go +++ b/precompiles/testutil/suite.go @@ -1,11 +1,13 @@ package testutil import ( + "math/big" "strings" + "time" "github.com/0glabs/0g-chain/app" "github.com/0glabs/0g-chain/chaincfg" - dasignersprecompile "github.com/0glabs/0g-chain/precompiles/dasigners" + precopmiles_common "github.com/0glabs/0g-chain/precompiles/common" "github.com/0glabs/0g-chain/x/bep3/types" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/ethereum/go-ethereum/common" @@ -44,15 +46,25 @@ type TestSigner struct { HexAddr string PrivKey cryptotypes.PrivKey Signer keyring.Signer + ValAddr sdk.ValAddress + AccAddr sdk.AccAddress } -func GenSigner() *TestSigner { +func (suite *PrecompileTestSuite) GenSigner() *TestSigner { var s TestSigner addr, priv := emtests.NewAddrKey() s.PrivKey = priv s.Addr = addr - s.HexAddr = dasignersprecompile.ToLowerHexWithoutPrefix(s.Addr) + s.HexAddr = precopmiles_common.ToLowerHexWithoutPrefix(s.Addr) s.Signer = emtests.NewSigner(priv) + valAddr, _ := sdk.ValAddressFromHex(s.HexAddr) + accAddr, _ := sdk.AccAddressFromHexUnsafe(s.HexAddr) + s.ValAddr = valAddr + s.AccAddr = accAddr + + // 10000 a0gi for test + suite.App.GetBankKeeper().MintCoins(suite.Ctx, "mint", sdk.NewCoins(chaincfg.MakeCoinForGasDenom(big.NewInt(10000000000)))) + suite.App.GetBankKeeper().SendCoinsFromModuleToAccount(suite.Ctx, "mint", accAddr, sdk.NewCoins(chaincfg.MakeCoinForGasDenom(big.NewInt(10000000000)))) return &s } @@ -70,7 +82,7 @@ func (suite *PrecompileTestSuite) SetupTest() { hexAddr := strings.ToLower(crypto.PubkeyToAddress(key.PublicKey).Hex()[2:]) valAddr, err := sdk.ValAddressFromHex(hexAddr) suite.Assert().NoError(err) - suite.Ctx = suite.App.NewContext(true, tmproto.Header{Height: 1, ChainID: app.TestChainId, ProposerAddress: consAddress}) + suite.Ctx = suite.App.NewContext(true, tmproto.Header{Height: 1, ChainID: app.TestChainId, ProposerAddress: consAddress, Time: time.Now()}) newValidator, err := stakingtypes.NewValidator(valAddr, privkey.PubKey(), stakingtypes.Description{}) suite.Assert().NoError(err) err = suite.StakingKeeper.SetValidatorByConsAddr(suite.Ctx, newValidator) diff --git a/proto/zgc/precisebank/v1/genesis.proto b/proto/zgc/precisebank/v1/genesis.proto new file mode 100644 index 00000000..7a87416e --- /dev/null +++ b/proto/zgc/precisebank/v1/genesis.proto @@ -0,0 +1,42 @@ +syntax = "proto3"; +package zgc.precisebank.v1; + +import "cosmos_proto/cosmos.proto"; +import "gogoproto/gogo.proto"; + +option go_package = "github.com/0glabs/0g-chain/x/precisebank/types"; + +// GenesisState defines the precisebank module's genesis state. +message GenesisState { + // balances is a list of all the balances in the precisebank module. + repeated FractionalBalance balances = 1 [ + (gogoproto.castrepeated) = "FractionalBalances", + (gogoproto.nullable) = false + ]; + + // remainder is an internal value of how much extra fractional digits are + // still backed by the reserve, but not assigned to any account. + string remainder = 2 [ + (cosmos_proto.scalar) = "cosmos.Int", + (gogoproto.customtype) = "cosmossdk.io/math.Int", + (gogoproto.nullable) = false + ]; +} + +// FractionalBalance defines the fractional portion of an account balance +message FractionalBalance { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + // address is the address of the balance holder. + string address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + + // amount indicates amount of only the fractional balance owned by the + // address. FractionalBalance currently only supports tracking 1 single asset, + // e.g. fractional balances of ukava. + string amount = 2 [ + (cosmos_proto.scalar) = "cosmos.Int", + (gogoproto.customtype) = "cosmossdk.io/math.Int", + (gogoproto.nullable) = false + ]; +} diff --git a/proto/zgc/precisebank/v1/query.proto b/proto/zgc/precisebank/v1/query.proto new file mode 100644 index 00000000..2561d622 --- /dev/null +++ b/proto/zgc/precisebank/v1/query.proto @@ -0,0 +1,62 @@ +syntax = "proto3"; +package zgc.precisebank.v1; + +import "cosmos/base/v1beta1/coin.proto"; +import "gogoproto/gogo.proto"; +import "google/api/annotations.proto"; + +option go_package = "github.com/0glabs/0g-chain/x/precisebank/types"; +option (gogoproto.goproto_getters_all) = false; + +// Query defines the gRPC querier service for precisebank module +service Query { + // TotalFractionalBalances returns the total sum of all fractional balances + // managed by the precisebank module. + rpc TotalFractionalBalances(QueryTotalFractionalBalancesRequest) returns (QueryTotalFractionalBalancesResponse) { + option (google.api.http).get = "/0g/precisebank/v1/total_fractional_balances"; + } + + // Remainder returns the amount backed by the reserve, but not yet owned by + // any account, i.e. not in circulation. + rpc Remainder(QueryRemainderRequest) returns (QueryRemainderResponse) { + option (google.api.http).get = "/0g/precisebank/v1/remainder"; + } + + // FractionalBalance returns only the fractional balance of an address. This + // does not include any integer balance. + rpc FractionalBalance(QueryFractionalBalanceRequest) returns (QueryFractionalBalanceResponse) { + option (google.api.http).get = "/0g/precisebank/v1/fractional_balance/{address}"; + } +} + +// QueryTotalFractionalBalancesRequest defines the request type for Query/TotalFractionalBalances method. +message QueryTotalFractionalBalancesRequest {} + +// QueryTotalFractionalBalancesResponse defines the response type for Query/TotalFractionalBalances method. +message QueryTotalFractionalBalancesResponse { + // total is the total sum of all fractional balances managed by the precisebank + // module. + cosmos.base.v1beta1.Coin total = 1 [(gogoproto.nullable) = false]; +} + +// QueryRemainderRequest defines the request type for Query/Remainder method. +message QueryRemainderRequest {} + +// QueryRemainderResponse defines the response type for Query/Remainder method. +message QueryRemainderResponse { + // remainder is the amount backed by the reserve, but not yet owned by any + // account, i.e. not in circulation. + cosmos.base.v1beta1.Coin remainder = 1 [(gogoproto.nullable) = false]; +} + +// QueryFractionalBalanceRequest defines the request type for Query/FractionalBalance method. +message QueryFractionalBalanceRequest { + // address is the account address to query fractional balance for. + string address = 1; +} + +// QueryFractionalBalanceResponse defines the response type for Query/FractionalBalance method. +message QueryFractionalBalanceResponse { + // fractional_balance is the fractional balance of the address. + cosmos.base.v1beta1.Coin fractional_balance = 1 [(gogoproto.nullable) = false]; +} diff --git a/tests/e2e-ibc/chainconfig.go b/tests/e2e-ibc/chainconfig.go new file mode 100644 index 00000000..b8a2a8a9 --- /dev/null +++ b/tests/e2e-ibc/chainconfig.go @@ -0,0 +1,52 @@ +package main + +import ( + "os" + + "github.com/strangelove-ventures/interchaintest/v7/chain/cosmos" + "github.com/strangelove-ventures/interchaintest/v7/ibc" + "github.com/strangelove-ventures/interchaintest/v7/testutil" +) + +const ( + KavaTestChainId = "kava_8888-1" + KavaEvmTestChainId = int64(8888) +) + +func DefaultKavaChainConfig(chainId string) ibc.ChainConfig { + kavaImageTag := os.Getenv("KAVA_TAG") + if kavaImageTag == "" { + kavaImageTag = "v0.26.0-rocksdb" + } + + // app.toml overrides + jsonRpcOverrides := make(testutil.Toml) + jsonRpcOverrides["address"] = "0.0.0.0:8545" + appTomlOverrides := make(testutil.Toml) + appTomlOverrides["json-rpc"] = jsonRpcOverrides + + // genesis param overrides + genesis := []cosmos.GenesisKV{ + cosmos.NewGenesisKV("consensus_params.block.max_gas", "20000000"), + cosmos.NewGenesisKV("app_state.evm.params.evm_denom", "akava"), + // update for fast voting periods + cosmos.NewGenesisKV("app_state.gov.params.voting_period", "10s"), + cosmos.NewGenesisKV("app_state.gov.params.min_deposit.0.denom", "ukava"), + } + + return ibc.ChainConfig{ + Type: "cosmos", + ChainID: chainId, + Images: []ibc.DockerImage{{Repository: "kava/kava", Version: kavaImageTag, UidGid: "0:0"}}, + // Images: []ibc.DockerImage{{Repository: "ghcr.io/strangelove-ventures/heighliner/kava", Version: "v0.26.0", UidGid: "1025:1025"}}, + Bin: "kava", + Bech32Prefix: "kava", + Denom: "ukava", + GasPrices: "0ukava", // 0 gas price makes calculating expected balances simpler + GasAdjustment: 1.5, + TrustingPeriod: "168h0m0s", + ModifyGenesis: cosmos.ModifyGenesis(genesis), + ExposeAdditionalPorts: []string{"8545/tcp"}, + ConfigFileOverrides: map[string]any{"config/app.toml": appTomlOverrides}, + } +} diff --git a/tests/e2e-ibc/conformance_test.go b/tests/e2e-ibc/conformance_test.go new file mode 100644 index 00000000..a3c6ccd9 --- /dev/null +++ b/tests/e2e-ibc/conformance_test.go @@ -0,0 +1,59 @@ +package main_test + +import ( + "context" + "fmt" + "testing" + "time" + + "go.uber.org/zap/zaptest" + + "github.com/strangelove-ventures/interchaintest/v7" + "github.com/strangelove-ventures/interchaintest/v7/conformance" + "github.com/strangelove-ventures/interchaintest/v7/ibc" + "github.com/strangelove-ventures/interchaintest/v7/testreporter" + "github.com/stretchr/testify/require" + + kavainterchain "github.com/kava-labs/kava/tests/interchain" +) + +var ( + numFullNodes = 0 + numValidators = 1 +) + +func TestIbcConformance(t *testing.T) { + // t.Skip("skipping conformance test") + + ctx := context.Background() + + // setup chain factories: must be exactly two chains to run conformance between + cfs := make([]interchaintest.ChainFactory, 0) + cfs = append(cfs, + interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{ + { + Name: "kava", + ChainConfig: kavainterchain.DefaultKavaChainConfig(kavainterchain.KavaTestChainId), + // override default number of nodes to limit the number of ports we need to bind to + // running conformance tests without these limits result in errors that look like + // tendermint rpc client status: post failed: Post "http://127.0.0.1:": dial tcp 127.0.0.1:: connect: can't assign requested address + NumValidators: &numValidators, + NumFullNodes: &numFullNodes, + }, + {Name: "osmosis", Version: "v24.0.1", NumValidators: &numValidators, NumFullNodes: &numFullNodes}, + }), + ) + + // setup relayer factory + rfs := make([]interchaintest.RelayerFactory, 0) + rfs = append(rfs, + interchaintest.NewBuiltinRelayerFactory(ibc.CosmosRly, zaptest.NewLogger(t)), + ) + + // test reporter + f, err := interchaintest.CreateLogFile(fmt.Sprintf("%d.json", time.Now().Unix())) + require.NoError(t, err) + rep := testreporter.NewReporter(f) + + conformance.Test(t, ctx, cfs, rfs, rep) +} diff --git a/tests/e2e-ibc/erc20_test.go b/tests/e2e-ibc/erc20_test.go new file mode 100644 index 00000000..50eadf8d --- /dev/null +++ b/tests/e2e-ibc/erc20_test.go @@ -0,0 +1,290 @@ +package main_test + +import ( + "context" + "crypto/sha256" + "encoding/json" + "fmt" + "math/big" + "path/filepath" + "testing" + "time" + + "github.com/stretchr/testify/require" + "go.uber.org/zap/zaptest" + + "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + gov1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" + paramsutils "github.com/cosmos/cosmos-sdk/x/params/client/utils" + transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" + + "github.com/ethereum/go-ethereum/ethclient" + + "github.com/strangelove-ventures/interchaintest/v7" + "github.com/strangelove-ventures/interchaintest/v7/chain/cosmos" + "github.com/strangelove-ventures/interchaintest/v7/ibc" + "github.com/strangelove-ventures/interchaintest/v7/testreporter" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/client/erc20" + "github.com/0glabs/0g-chain/tests/e2e/runner" + "github.com/0glabs/0g-chain/tests/e2e/testutil" + kavainterchain "github.com/0glabs/0g-chain/tests/interchain" + "github.com/0glabs/0g-chain/tests/util" + evmutiltypes "github.com/0glabs/0g-chain/x/evmutil/types" +) + +// This test does the following: +// - set up a network with kava & cosmoshub w/ IBC channels between them +// - deploy an ERC20 to Kava EVM +// - configure Kava to support conversion of ERC20 to Cosmos Coin +// - IBC the sdk.Coin representation of the ERC20 to cosmoshub +func TestInterchainErc20(t *testing.T) { + app.SetSDKConfig() + ctx := context.Background() + + // Configure & run chains with interchaintest + cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{ + {Name: "kava", ChainConfig: kavainterchain.DefaultKavaChainConfig(kavainterchain.KavaTestChainId)}, + {Name: "gaia", Version: "v15.2.0", ChainConfig: ibc.ChainConfig{GasPrices: "0.0uatom"}}, + }) + + chains, err := cf.Chains(t.Name()) + require.NoError(t, err) + + ictKava := chains[0].(*cosmos.CosmosChain) + gaia := chains[1].(*cosmos.CosmosChain) + + client, network := interchaintest.DockerSetup(t) + + r := interchaintest.NewBuiltinRelayerFactory(ibc.CosmosRly, zaptest.NewLogger(t)). + Build(t, client, network) + + // configure interchain + const kavaGaiaIbcPath = "kava-gaia-ibc" + ic := interchaintest.NewInterchain().AddChain(ictKava). + AddChain(gaia). + AddRelayer(r, "relayer"). + AddLink(interchaintest.InterchainLink{ + Chain1: ictKava, + Chain2: gaia, + Relayer: r, + Path: kavaGaiaIbcPath, + }) + + // Log location + f, err := interchaintest.CreateLogFile(fmt.Sprintf("%d.json", time.Now().Unix())) + require.NoError(t, err) + // Reporter/logs + rep := testreporter.NewReporter(f) + eRep := rep.RelayerExecReporter(t) + + // Build interchain + err = ic.Build(ctx, eRep, interchaintest.InterchainBuildOptions{ + TestName: t.Name(), + Client: client, + NetworkID: network, + SkipPathCreation: false}, + ) + require.NoError(t, err) + + // Create and Fund User Wallets + fundAmount := math.NewInt(1e12) + + users := interchaintest.GetAndFundTestUsers(t, ctx, t.Name(), fundAmount, ictKava, gaia) + kavaUser := users[0] + gaiaUser := users[1] + + // wait for new block to ensure initial funding complete + height, err := ictKava.Height(ctx) + require.NoError(t, err) + h := height + for h <= height { + h, err = ictKava.Height(ctx) + require.NoError(t, err) + } + + gaiaChannelInfo, err := r.GetChannels(ctx, eRep, gaia.Config().ChainID) + require.NoError(t, err) + gaiaToKavaChannelID := gaiaChannelInfo[0].ChannelID + kavaToGaiaChannelID := gaiaChannelInfo[0].Counterparty.ChannelID + + // for simplified management of the chain, use kava's e2e framework for account management + // this skirts problems in interchaintest with needing coin type 60 + // there are exceptions in the relayer & ibc channel management that complicate setting the chain + // default coin type to 60 in the chain config. + // we need to fund an account and then all of kava's e2e testutil chain management will work. + + rpcUrl, err := ictKava.FullNodes[0].GetHostAddress(ctx, "26657/tcp") + require.NoError(t, err, "failed to find rpc URL") + grpcUrl, err := ictKava.FullNodes[0].GetHostAddress(ctx, "9090/tcp") + require.NoError(t, err, "failed to find grpc URL") + evmUrl, err := ictKava.FullNodes[0].GetHostAddress(ctx, "8545/tcp") + require.NoError(t, err, "failed to find evm URL") + + evmClient, err := ethclient.Dial(evmUrl) + require.NoError(t, err, "failed to connect to evm") + + // create a funded evm account to initialize the testutil.Chain + // use testutil.Chain for account management because the accounts play nicely with EVM & SDK sides + deployerMnemonic, err := util.RandomMnemonic() + require.NoError(t, err) + evmDeployer, err := util.NewEvmSignerFromMnemonic(evmClient, big.NewInt(kavainterchain.KavaEvmTestChainId), deployerMnemonic) + require.NoError(t, err) + + deployerKavaAddr := util.EvmToSdkAddress(evmDeployer.Address()) + err = ictKava.SendFunds(ctx, kavaUser.KeyName(), ibc.WalletAmount{ + Address: deployerKavaAddr.String(), + Denom: "ukava", + Amount: math.NewInt(1e10), + }) + require.NoError(t, err) + + // initialize testutil.Chain for account & tx management on both sdk & evm + kava, err := testutil.NewChain(t, &runner.ChainDetails{ + RpcUrl: rpcUrl, + GrpcUrl: grpcUrl, + EvmRpcUrl: evmUrl, + ChainId: kavainterchain.KavaTestChainId, + StakingDenom: "ukava", + }, deployerMnemonic) + require.NoError(t, err) + + deployer := kava.GetAccount("whale") + + // deploy ERC20 contract + usdtAddr, deployTx, usdt, err := erc20.DeployErc20( + deployer.EvmAuth, kava.EvmClient, + "Test Tether USD", "USDT", 6, + ) + require.NoError(t, err) + require.NotNil(t, usdtAddr) + require.NotNil(t, usdt) + + _, err = util.WaitForEvmTxReceipt(kava.EvmClient, deployTx.Hash(), 10*time.Second) + require.NoError(t, err) + + //////////////////////////////////////////// + // enable conversion from erc20 -> sdk.Coin + // (assumes there are none pre-configured!) + //////////////////////////////////////////// + // 1. Submit Proposal + sdkDenom := "tether/usdt" + rawCps, err := json.Marshal(evmutiltypes.NewConversionPairs( + evmutiltypes.NewConversionPair( + evmutiltypes.NewInternalEVMAddress(usdtAddr), + sdkDenom, + ), + )) + require.NoError(t, err) + + paramChange := paramsutils.ParamChangeProposalJSON{ + Title: "Enable erc20 conversion to sdk.Coin", + Description: ".", + Changes: paramsutils.ParamChangesJSON{ + paramsutils.ParamChangeJSON{ + Subspace: "evmutil", + Key: "EnabledConversionPairs", + Value: rawCps, + }, + }, + Deposit: "10000000ukava", + } + + _, err = legacyParamChangeProposal(ictKava.FullNodes[0], ctx, kavaUser.KeyName(), ¶mChange) + require.NoError(t, err, "error submitting param change proposal tx") + + // TODO: query proposal id. assuming it is 1 here. + propId := int64(1) + + // 2. Vote on Proposal + err = ictKava.VoteOnProposalAllValidators(ctx, propId, cosmos.ProposalVoteYes) + require.NoError(t, err, "failed to submit votes") + + height, _ = ictKava.Height(ctx) + _, err = cosmos.PollForProposalStatus(ctx, ictKava, height, height+10, propId, gov1beta1.StatusPassed) + require.NoError(t, err, "proposal status did not change to passed in expected number of blocks") + + // fund a user & mint them some usdt + user := kava.NewFundedAccount("tether-user", sdk.NewCoins(sdk.NewCoin("ukava", math.NewInt(1e7)))) + erc20FundAmt := big.NewInt(100e6) + mintTx, err := usdt.Mint(deployer.EvmAuth, user.EvmAddress, erc20FundAmt) + require.NoError(t, err) + + _, err = util.WaitForEvmTxReceipt(kava.EvmClient, mintTx.Hash(), 10*time.Second) + require.NoError(t, err) + // verify they have erc20 balance! + bal, err := usdt.BalanceOf(nil, user.EvmAddress) + require.NoError(t, err) + require.Equal(t, erc20FundAmt, bal) + + // convert the erc20 to sdk.Coin! + amountToConvert := math.NewInt(50e6) + msg := evmutiltypes.NewMsgConvertERC20ToCoin( + evmutiltypes.NewInternalEVMAddress(user.EvmAddress), + user.SdkAddress, + evmutiltypes.NewInternalEVMAddress(usdtAddr), + amountToConvert, + ) + convertTx := util.KavaMsgRequest{ + Msgs: []sdk.Msg{&msg}, + GasLimit: 4e5, + FeeAmount: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(400))), + Data: "converting sdk coin to erc20", + } + res := user.SignAndBroadcastKavaTx(convertTx) + require.NoError(t, res.Err) + + // check balance of cosmos coin! + sdkBalance := kava.QuerySdkForBalances(user.SdkAddress) + require.Equal(t, amountToConvert, sdkBalance.AmountOf(sdkDenom)) + + // IBC the newly minted sdk.Coin to gaia + dstAddress := gaiaUser.FormattedAddress() + transfer := ibc.WalletAmount{ + Address: dstAddress, + Denom: ictKava.Config().Denom, + Amount: amountToConvert, + } + _, err = ictKava.SendIBCTransfer(ctx, kavaToGaiaChannelID, kavaUser.KeyName(), transfer, ibc.TransferOptions{}) + require.NoError(t, err) + + // manually flush packets so we don't need to wait for the relayer + require.NoError(t, r.Flush(ctx, eRep, kavaGaiaIbcPath, kavaToGaiaChannelID)) + + // determine IBC denom & check gaia balance + srcDenomTrace := transfertypes.ParseDenomTrace(transfertypes.GetPrefixedDenom("transfer", gaiaToKavaChannelID, ictKava.Config().Denom)) + erc20OnGaiaDenom := srcDenomTrace.IBCDenom() + + gaiaBal, err := gaia.GetBalance(ctx, dstAddress, erc20OnGaiaDenom) + require.NoError(t, err) + + require.Equal(t, amountToConvert, gaiaBal) +} + +// copied from https://github.com/strangelove-ventures/interchaintest/blob/7272afc780da6e2c99b2d2b3d084d5a3b1c6895f/chain/cosmos/chain_node.go#L1292 +// but changed "submit-proposal" to "submit-legacy-proposal" +func legacyParamChangeProposal(tn *cosmos.ChainNode, ctx context.Context, keyName string, prop *paramsutils.ParamChangeProposalJSON) (string, error) { + content, err := json.Marshal(prop) + if err != nil { + return "", err + } + + hash := sha256.Sum256(content) + proposalFilename := fmt.Sprintf("%x.json", hash) + err = tn.WriteFile(ctx, content, proposalFilename) + if err != nil { + return "", fmt.Errorf("writing param change proposal: %w", err) + } + + proposalPath := filepath.Join(tn.HomeDir(), proposalFilename) + + command := []string{ + "gov", "submit-legacy-proposal", + "param-change", + proposalPath, + } + + return tn.ExecTx(ctx, keyName, command...) +} diff --git a/tests/e2e-ibc/go.mod b/tests/e2e-ibc/go.mod new file mode 100644 index 00000000..e5e6c1f1 --- /dev/null +++ b/tests/e2e-ibc/go.mod @@ -0,0 +1,297 @@ +module github.com/kava-labs/kava/tests/interchain + +go 1.21.9 + +require ( + cosmossdk.io/math v1.3.0 + github.com/cosmos/ibc-go/v7 v7.4.0 + github.com/ethereum/go-ethereum v1.10.26 + github.com/stretchr/testify v1.9.0 + go.uber.org/zap v1.26.0 +) + +require ( + github.com/cosmos/cosmos-sdk v0.47.10 + github.com/kava-labs/kava v0.0.0-00010101000000-000000000000 + github.com/strangelove-ventures/interchaintest/v7 v7.0.1-0.20240506191732-71a15c29f2b7 +) + +require ( + cloud.google.com/go v0.112.0 // indirect + cloud.google.com/go/compute v1.24.0 // indirect + cloud.google.com/go/compute/metadata v0.2.3 // indirect + cloud.google.com/go/iam v1.1.6 // indirect + cloud.google.com/go/storage v1.36.0 // indirect + cosmossdk.io/api v0.3.1 // indirect + cosmossdk.io/core v0.6.1 // indirect + cosmossdk.io/depinject v1.0.0-alpha.4 // indirect + cosmossdk.io/errors v1.0.1 // indirect + cosmossdk.io/log v1.3.1 // indirect + cosmossdk.io/tools/rosetta v0.2.1 // indirect + filippo.io/edwards25519 v1.0.0 // indirect + github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect + github.com/99designs/keyring v1.2.2 // indirect + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/ChainSafe/go-schnorrkel v1.0.0 // indirect + github.com/DataDog/zstd v1.5.5 // indirect + github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect + github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/StackExchange/wmi v1.2.1 // indirect + github.com/StirlingMarketingGroup/go-namecase v1.0.0 // indirect + github.com/VictoriaMetrics/fastcache v1.12.1 // indirect + github.com/armon/go-metrics v0.4.1 // indirect + github.com/avast/retry-go/v4 v4.5.0 // indirect + github.com/aws/aws-sdk-go v1.44.203 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect + github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect + github.com/btcsuite/btcd v0.24.0 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect + github.com/btcsuite/btcd/btcutil v1.1.5 // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect + github.com/cenkalti/backoff/v4 v4.1.3 // indirect + github.com/cespare/xxhash v1.1.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/chzyer/readline v1.5.1 // indirect + github.com/cockroachdb/errors v1.11.1 // indirect + github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect + github.com/cockroachdb/pebble v1.1.0 // indirect + github.com/cockroachdb/redact v1.1.5 // indirect + github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect + github.com/coinbase/rosetta-sdk-go/types v1.0.0 // indirect + github.com/cometbft/cometbft v0.37.9 // indirect + github.com/cometbft/cometbft-db v0.9.1 // indirect + github.com/confio/ics23/go v0.9.0 // indirect + github.com/cosmos/btcutil v1.0.5 // indirect + github.com/cosmos/cosmos-db v1.0.2 // indirect + github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect + github.com/cosmos/go-bip39 v1.0.0 // indirect + github.com/cosmos/gogogateway v1.2.0 // indirect + github.com/cosmos/gogoproto v1.4.10 // indirect + github.com/cosmos/iavl v1.2.0 // indirect + github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7 v7.1.3 // indirect + github.com/cosmos/ibc-go/modules/capability v1.0.0-rc1 // indirect + github.com/cosmos/ics23/go v0.10.0 // indirect + github.com/cosmos/interchain-security/v3 v3.1.1-0.20231102122221-81650a84f989 // indirect + github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect + github.com/cosmos/rosetta-sdk-go v0.10.0 // indirect + github.com/creachadair/taskgroup v0.4.2 // indirect + github.com/danieljoos/wincred v1.1.2 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/deckarep/golang-set v1.8.0 // indirect + github.com/decred/base58 v1.0.4 // indirect + github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v2 v2.0.1 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect + github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect + github.com/dgraph-io/badger/v2 v2.2007.4 // indirect + github.com/dgraph-io/ristretto v0.1.1 // indirect + github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect + github.com/docker/distribution v2.8.2+incompatible // indirect + github.com/docker/docker v24.0.7+incompatible // indirect + github.com/docker/go-connections v0.4.0 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/dvsekhvalnov/jose2go v1.6.0 // indirect + github.com/edsrzf/mmap-go v1.0.0 // indirect + github.com/emicklei/dot v1.6.1 // indirect + github.com/evmos/ethermint v0.21.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect + github.com/getsentry/sentry-go v0.27.0 // indirect + github.com/go-kit/kit v0.13.0 // indirect + github.com/go-kit/log v0.2.1 // indirect + github.com/go-logfmt/logfmt v0.6.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect + github.com/go-stack/stack v1.8.1 // indirect + github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect + github.com/gogo/googleapis v1.4.1 // indirect + github.com/gogo/protobuf v1.3.3 // indirect + github.com/golang/glog v1.2.0 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/mock v1.6.0 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect + github.com/google/btree v1.1.2 // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/google/orderedcode v0.0.1 // indirect + github.com/google/s2a-go v0.1.7 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect + github.com/googleapis/gax-go/v2 v2.12.0 // indirect + github.com/gorilla/handlers v1.5.1 // indirect + github.com/gorilla/mux v1.8.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect + github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect + github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect + github.com/gtank/merlin v0.1.1 // indirect + github.com/gtank/ristretto255 v0.1.2 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-getter v1.7.5 // indirect + github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/go-safetemp v1.0.0 // indirect + github.com/hashicorp/go-version v1.6.0 // indirect + github.com/hashicorp/golang-lru v1.0.2 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/hdevalence/ed25519consensus v0.1.0 // indirect + github.com/holiman/bloomfilter/v2 v2.0.3 // indirect + github.com/holiman/uint256 v1.2.4 // indirect + github.com/huandu/skiplist v1.2.0 // indirect + github.com/huin/goupnp v1.3.0 // indirect + github.com/iancoleman/orderedmap v0.2.0 // indirect + github.com/icza/dyno v0.0.0-20220812133438-f0b6f8a18845 // indirect + github.com/improbable-eng/grpc-web v0.15.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/ipfs/go-cid v0.4.1 // indirect + github.com/jackpal/go-nat-pmp v1.0.2 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect + github.com/jmhodges/levigo v1.0.0 // indirect + github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/klauspost/cpuid/v2 v2.2.4 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/lib/pq v1.10.7 // indirect + github.com/libp2p/go-buffer-pool v0.1.0 // indirect + github.com/libp2p/go-libp2p v0.27.8 // indirect + github.com/linxGnu/grocksdb v1.8.13 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/manifoldco/promptui v0.9.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.14 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/mimoo/StrobeGo v0.0.0-20220103164710-9a04d6ca976b // indirect + github.com/minio/highwayhash v1.0.2 // indirect + github.com/minio/sha256-simd v1.0.0 // indirect + github.com/misko9/go-substrate-rpc-client/v4 v4.0.0 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/mitchellh/go-testing-interface v1.14.1 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/mr-tron/base58 v1.2.0 // indirect + github.com/mtibben/percent v0.2.1 // indirect + github.com/multiformats/go-base32 v0.1.0 // indirect + github.com/multiformats/go-base36 v0.2.0 // indirect + github.com/multiformats/go-multiaddr v0.9.0 // indirect + github.com/multiformats/go-multibase v0.2.0 // indirect + github.com/multiformats/go-multicodec v0.8.1 // indirect + github.com/multiformats/go-multihash v0.2.1 // indirect + github.com/multiformats/go-varint v0.0.7 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.0-rc2 // indirect + github.com/pelletier/go-toml v1.9.5 // indirect + github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/petermattis/goid v0.0.0-20231207134359-e60b3f734c67 // indirect + github.com/pierrec/xxHash v0.1.5 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_golang v1.17.0 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.44.0 // indirect + github.com/prometheus/procfs v0.13.0 // indirect + github.com/prometheus/tsdb v0.7.1 // indirect + github.com/rakyll/statik v0.1.7 // indirect + github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect + github.com/rivo/uniseg v0.4.3 // indirect + github.com/rjeczalik/notify v0.9.1 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect + github.com/rs/cors v1.8.3 // indirect + github.com/rs/zerolog v1.32.0 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/sasha-s/go-deadlock v0.3.1 // indirect + github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spaolacci/murmur3 v1.1.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect + github.com/spf13/cobra v1.8.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/spf13/viper v1.18.2 // indirect + github.com/status-im/keycard-go v0.2.0 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect + github.com/tendermint/go-amino v0.16.0 // indirect + github.com/tidwall/btree v1.7.0 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect + github.com/tyler-smith/go-bip32 v1.0.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/ulikunitz/xz v0.5.11 // indirect + github.com/vedhavyas/go-subkey/v2 v2.0.0 // indirect + github.com/zondax/hid v0.9.2 // indirect + github.com/zondax/ledger-go v0.14.3 // indirect + go.etcd.io/bbolt v1.3.8 // indirect + go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 // indirect + go.opentelemetry.io/otel v1.22.0 // indirect + go.opentelemetry.io/otel/metric v1.22.0 // indirect + go.opentelemetry.io/otel/trace v1.22.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/oauth2 v0.17.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/term v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + golang.org/x/tools v0.20.0 // indirect + google.golang.org/api v0.162.0 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect + google.golang.org/grpc v1.63.2 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + lukechampine.com/blake3 v1.1.7 // indirect + lukechampine.com/uint128 v1.2.0 // indirect + modernc.org/cc/v3 v3.40.0 // indirect + modernc.org/ccgo/v3 v3.16.13 // indirect + modernc.org/libc v1.24.1 // indirect + modernc.org/mathutil v1.5.0 // indirect + modernc.org/memory v1.6.0 // indirect + modernc.org/opt v0.1.3 // indirect + modernc.org/sqlite v1.25.0 // indirect + modernc.org/strutil v1.1.3 // indirect + modernc.org/token v1.0.1 // indirect + nhooyr.io/websocket v1.8.7 // indirect + pgregory.net/rapid v1.1.0 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect +) + +replace ( + // use cosmos fork of keyring + github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 + // Use cometbft fork of tendermint + github.com/cometbft/cometbft => github.com/kava-labs/cometbft v0.37.9-kava.1 + github.com/cometbft/cometbft-db => github.com/kava-labs/cometbft-db v0.9.1-kava.2 + // Use cosmos-sdk fork with backported fix for unsafe-reset-all, staking transfer events, and custom tally handler support + github.com/cosmos/cosmos-sdk => github.com/kava-labs/cosmos-sdk v0.47.10-iavl-v1-kava.1 + github.com/ethereum/go-ethereum => github.com/Kava-Labs/go-ethereum v1.10.27-0.20240308170502-da7973e5eee0 + // Use ethermint fork that respects min-gas-price with NoBaseFee true and london enabled, and includes eip712 support + github.com/evmos/ethermint => github.com/kava-labs/ethermint v0.21.1-0.20240703152838-badab86e5aba + github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 + // github.com/ComposableFi/go-subkey/v2 => github.com/vedhavyas/go-subkey/v2 v2.0.0 + github.com/misko9/go-substrate-rpc-client/v4 => github.com/faddat/go-substrate-rpc-client/v4 v4.0.1-0.20240402155230-48db8c110afe + + // stick with compatible version or x/exp in v0.47.x line + golang.org/x/exp => golang.org/x/exp v0.0.0-20230711153332-06a737ee72cb +) + +replace github.com/kava-labs/kava => ../../ diff --git a/tests/e2e-ibc/go.sum b/tests/e2e-ibc/go.sum new file mode 100644 index 00000000..de6ee795 --- /dev/null +++ b/tests/e2e-ibc/go.sum @@ -0,0 +1,1942 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= +cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= +cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= +cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= +cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= +cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= +cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= +cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= +cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= +cloud.google.com/go v0.112.0 h1:tpFCD7hpHFlQ8yPwT3x+QeXqc2T6+n6T+hmABHfDUSM= +cloud.google.com/go v0.112.0/go.mod h1:3jEEVwZ/MHU4djK5t5RHuKOA/GbLddgTdVubX1qnPD4= +cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= +cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= +cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= +cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4= +cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4= +cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0= +cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ= +cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk= +cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o= +cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s= +cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0= +cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY= +cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw= +cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI= +cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= +cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA= +cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY= +cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s= +cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM= +cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI= +cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY= +cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI= +cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= +cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= +cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= +cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= +cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= +cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= +cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= +cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg= +cloud.google.com/go/compute v1.24.0/go.mod h1:kw1/T+h/+tK2LJK0wiPPx1intgdAM3j/g3hFDlscY40= +cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= +cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= +cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= +cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs= +cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc= +cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM= +cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ= +cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KFMQQNSThKo= +cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE= +cloud.google.com/go/datalabeling v0.5.0/go.mod h1:TGcJ0G2NzcsXSE/97yWjIZO0bXj0KbVlINXMG9ud42I= +cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ= +cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4cK3vbhkeo= +cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo= +cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ= +cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4= +cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0= +cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8= +cloud.google.com/go/documentai v1.7.0/go.mod h1:lJvftZB5NRiFSX4moiye1SMxHx0Bc3x1+p9e/RfXYiU= +cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU= +cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y= +cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg= +cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk= +cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w= +cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk= +cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg= +cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM= +cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA= +cloud.google.com/go/gkeconnect v0.5.0/go.mod h1:c5lsNAg5EwAy7fkqX/+goqFsU1Da/jQFqArp+wGNr/o= +cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A= +cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0= +cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0= +cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= +cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= +cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= +cloud.google.com/go/iam v1.1.6 h1:bEa06k05IO4f4uJonbB5iAgKTPpABy1ayxaIZV/GHVc= +cloud.google.com/go/iam v1.1.6/go.mod h1:O0zxdPeGBoFdWW3HWmBxJsk0pfvNM/p/qa82rWOGTwI= +cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= +cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= +cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= +cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= +cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= +cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= +cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= +cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM= +cloud.google.com/go/metastore v1.5.0/go.mod h1:2ZNrDcQwghfdtCwJ33nM0+GrBGlVuh8rakL3vdPY3XY= +cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s= +cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA= +cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o= +cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ= +cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU= +cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY= +cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34= +cloud.google.com/go/osconfig v1.7.0/go.mod h1:oVHeCeZELfJP7XLxcBGTMBvRO+1nQ5tFG9VQTmYS2Fs= +cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg= +cloud.google.com/go/oslogin v1.4.0/go.mod h1:YdgMXWRaElXz/lDk1Na6Fh5orF7gvmJ0FGLIs9LId4E= +cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU= +cloud.google.com/go/phishingprotection v0.5.0/go.mod h1:Y3HZknsK9bc9dMi+oE8Bim0lczMU6hrX0UpADuMefr0= +cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA= +cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0= +cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4= +cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o= +cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk= +cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7dd5NwwNQUErSgEDit1DLNTdo= +cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg= +cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4= +cloud.google.com/go/recommender v1.5.0/go.mod h1:jdoeiBIVrJe9gQjwd759ecLJbxCDED4A6p+mqoqDvTg= +cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c= +cloud.google.com/go/redis v1.7.0/go.mod h1:V3x5Jq1jzUcg+UNsRvdmsfuFnit1cfe3Z/PGyq/lm4Y= +cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A= +cloud.google.com/go/retail v1.8.0/go.mod h1:QblKS8waDmNUhghY2TI9O3JLlFk8jybHeV4BF19FrE4= +cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY= +cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s= +cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI= +cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA= +cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4= +cloud.google.com/go/security v1.7.0/go.mod h1:mZklORHl6Bg7CNnnjLH//0UlAlaXqiG7Lb9PsPXLfD0= +cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU= +cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU= +cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc= +cloud.google.com/go/servicedirectory v1.4.0/go.mod h1:gH1MUaZCgtP7qQiI+F+A+OpeKF/HQWgtAddhTbhL2bs= +cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg= +cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= +cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= +cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= +cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= +cloud.google.com/go/storage v1.36.0 h1:P0mOkAcaJxhCTvAkMhxMfrTKiNcub4YmmPBtlhAyTr8= +cloud.google.com/go/storage v1.36.0/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8= +cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= +cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= +cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= +cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4= +cloud.google.com/go/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0= +cloud.google.com/go/vision/v2 v2.2.0/go.mod h1:uCdV4PpN1S0jyCyq8sIM42v2Y6zOLkZs+4R9LrGYwFo= +cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo= +cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE= +cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= +cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= +cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= +cosmossdk.io/api v0.3.1 h1:NNiOclKRR0AOlO4KIqeaG6PS6kswOMhHD0ir0SscNXE= +cosmossdk.io/api v0.3.1/go.mod h1:DfHfMkiNA2Uhy8fj0JJlOCYOBp4eWUUJ1te5zBGNyIw= +cosmossdk.io/core v0.6.1 h1:OBy7TI2W+/gyn2z40vVvruK3di+cAluinA6cybFbE7s= +cosmossdk.io/core v0.6.1/go.mod h1:g3MMBCBXtxbDWBURDVnJE7XML4BG5qENhs0gzkcpuFA= +cosmossdk.io/depinject v1.0.0-alpha.4 h1:PLNp8ZYAMPTUKyG9IK2hsbciDWqna2z1Wsl98okJopc= +cosmossdk.io/depinject v1.0.0-alpha.4/go.mod h1:HeDk7IkR5ckZ3lMGs/o91AVUc7E596vMaOmslGFM3yU= +cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= +cosmossdk.io/errors v1.0.1/go.mod h1:MeelVSZThMi4bEakzhhhE/CKqVv3nOJDA25bIqRDu/U= +cosmossdk.io/log v1.3.1 h1:UZx8nWIkfbbNEWusZqzAx3ZGvu54TZacWib3EzUYmGI= +cosmossdk.io/log v1.3.1/go.mod h1:2/dIomt8mKdk6vl3OWJcPk2be3pGOS8OQaLUM/3/tCM= +cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= +cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= +cosmossdk.io/simapp v0.0.0-20231127212628-044ff4d8c015 h1:ARUqouMWNreV8e5wxPberry+tm+Uk+1eeJDt3KXQEn0= +cosmossdk.io/simapp v0.0.0-20231127212628-044ff4d8c015/go.mod h1:VNknW36ZIgwkjKtb6eyA4RZ7x9+ZpKMVCsAUA6bFWnk= +cosmossdk.io/tools/rosetta v0.2.1 h1:ddOMatOH+pbxWbrGJKRAawdBkPYLfKXutK9IETnjYxw= +cosmossdk.io/tools/rosetta v0.2.1/go.mod h1:Pqdc1FdvkNV3LcNIkYWt2RQY6IP1ge6YWZk8MhhO9Hw= +filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek= +filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= +github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= +github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/ChainSafe/go-schnorrkel v1.0.0 h1:3aDA67lAykLaG1y3AOjs88dMxC88PgUuHRrLeDnvGIM= +github.com/ChainSafe/go-schnorrkel v1.0.0/go.mod h1:dpzHYVxLZcp8pjlV+O+UR8K0Hp/z7vcchBSbMBEhCw4= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= +github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc= +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U= +github.com/Kava-Labs/go-ethereum v1.10.27-0.20240308170502-da7973e5eee0 h1:pPFzOjEZmihLk70TQRPUCWs8uar6nfh4vZ/I1r0zeso= +github.com/Kava-Labs/go-ethereum v1.10.27-0.20240308170502-da7973e5eee0/go.mod h1:/6CsT5Ceen2WPLI/oCA3xMcZ5sWMF/D46SjM/ayY0Oo= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= +github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= +github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= +github.com/StirlingMarketingGroup/go-namecase v1.0.0 h1:2CzaNtCzc4iNHirR+5ru9OzGg8rQp860gqLBFqRI02Y= +github.com/StirlingMarketingGroup/go-namecase v1.0.0/go.mod h1:ZsoSKcafcAzuBx+sndbxHu/RjDcDTrEdT4UvhniHfio= +github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= +github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= +github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/adlio/schema v1.3.3 h1:oBJn8I02PyTB466pZO1UZEn1TV5XLlifBSyMrmHl/1I= +github.com/adlio/schema v1.3.3/go.mod h1:1EsRssiv9/Ce2CMzq5DoL7RiMshhuigQxrR4DMV9fHg= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= +github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= +github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/avast/retry-go/v4 v4.5.0 h1:QoRAZZ90cj5oni2Lsgl2GW8mNTnUCnmpx/iKpwVisHg= +github.com/avast/retry-go/v4 v4.5.0/go.mod h1:7hLEXp0oku2Nir2xBAsg0PTphp9z71bN5Aq1fboC3+I= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= +github.com/aws/aws-sdk-go v1.44.203 h1:pcsP805b9acL3wUqa4JR2vg1k2wnItkDYNvfmcy6F+U= +github.com/aws/aws-sdk-go v1.44.203/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= +github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 h1:41iFGWnSlI2gVpmOtVTJZNodLdLQLn/KsJqFvXwnd/s= +github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= +github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= +github.com/btcsuite/btcd v0.24.0 h1:gL3uHE/IaFj6fcZSu03SvqPMSx7s/dPzfpG/atRwWdo= +github.com/btcsuite/btcd v0.24.0/go.mod h1:K4IDc1593s8jKXIF7yS7yCTSxrknB9z0STzc2j6XgE4= +github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= +github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= +github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= +github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= +github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= +github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce h1:YtWJF7RHm2pYCvA5t0RPmAaLUhREsKuKd+SLhxFbFeQ= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= +github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= +github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= +github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= +github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI= +github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= +github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= +github.com/cockroachdb/apd/v2 v2.0.2 h1:weh8u7Cneje73dDh+2tEVLUvyBc89iwepWCD8b8034E= +github.com/cockroachdb/apd/v2 v2.0.2/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= +github.com/cockroachdb/errors v1.11.1 h1:xSEW75zKaKCWzR3OfxXUxgrk/NtT4G1MiOv5lWZazG8= +github.com/cockroachdb/errors v1.11.1/go.mod h1:8MUxA3Gi6b25tYlFEBGLf+D8aISL+M4MIpiWMSNRfxw= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/pebble v1.1.0 h1:pcFh8CdCIt2kmEpK0OIatq67Ln9uGDYY3d5XnE0LJG4= +github.com/cockroachdb/pebble v1.1.0/go.mod h1:sEHm5NOXxyiAoKWhoFxT8xMgd/f3RA6qUqQ1BXKrh2E= +github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= +github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/coinbase/rosetta-sdk-go/types v1.0.0 h1:jpVIwLcPoOeCR6o1tU+Xv7r5bMONNbHU7MuEHboiFuA= +github.com/coinbase/rosetta-sdk-go/types v1.0.0/go.mod h1:eq7W2TMRH22GTW0N0beDnN931DW0/WOI1R2sdHNHG4c= +github.com/confio/ics23/go v0.9.0 h1:cWs+wdbS2KRPZezoaaj+qBleXgUk5WOQFMP3CQFGTr4= +github.com/confio/ics23/go v0.9.0/go.mod h1:4LPZ2NYqnYIVRklaozjNR1FScgDJ2s5Xrp+e/mYVRak= +github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= +github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= +github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= +github.com/cosmos/cosmos-db v1.0.2 h1:hwMjozuY1OlJs/uh6vddqnk9j7VamLv+0DBlbEXbAKs= +github.com/cosmos/cosmos-db v1.0.2/go.mod h1:Z8IXcFJ9PqKK6BIsVOB3QXtkKoqUOp1vRvPT39kOXEA= +github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= +github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= +github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= +github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= +github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= +github.com/cosmos/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiKxTE= +github.com/cosmos/gogogateway v1.2.0/go.mod h1:iQpLkGWxYcnCdz5iAdLcRBSw3h7NXeOkZ4GUkT+tbFI= +github.com/cosmos/gogoproto v1.4.2/go.mod h1:cLxOsn1ljAHSV527CHOtaIP91kK6cCrZETRBrkzItWU= +github.com/cosmos/gogoproto v1.4.10 h1:QH/yT8X+c0F4ZDacDv3z+xE3WU1P1Z3wQoLMBRJoKuI= +github.com/cosmos/gogoproto v1.4.10/go.mod h1:3aAZzeRWpAwr+SS/LLkICX2/kDFyaYVzckBDzygIxek= +github.com/cosmos/iavl v1.2.0 h1:kVxTmjTh4k0Dh1VNL046v6BXqKziqMDzxo93oh3kOfM= +github.com/cosmos/iavl v1.2.0/go.mod h1:HidWWLVAtODJqFD6Hbne2Y0q3SdxByJepHUOeoH4LiI= +github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7 v7.1.3 h1:MZGDMETv72suFpTAD6VPGqSIm1FJcChtk2HmVh9D+Bo= +github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7 v7.1.3/go.mod h1:UvDmcGIWJPIytq+Q78/ff5NTOsuX/7IrNgEugTW5i0s= +github.com/cosmos/ibc-go/modules/capability v1.0.0-rc1 h1:BvSKnPFKxL+TTSLxGKwJN4x0ndCZj0yfXhSvmsQztSA= +github.com/cosmos/ibc-go/modules/capability v1.0.0-rc1/go.mod h1:A+CxAQdn2j6ihDTbClpEEBdHthWgAUAcHbRAQPY8sl4= +github.com/cosmos/ibc-go/v7 v7.4.0 h1:8FqYMptvksgMvlbN4UW9jFxTXzsPyfAzEZurujXac8M= +github.com/cosmos/ibc-go/v7 v7.4.0/go.mod h1:L/KaEhzV5TGUCTfGysVgMBQtl5Dm7hHitfpk+GIeoAo= +github.com/cosmos/ics23/go v0.10.0 h1:iXqLLgp2Lp+EdpIuwXTYIQU+AiHj9mOC2X9ab++bZDM= +github.com/cosmos/ics23/go v0.10.0/go.mod h1:ZfJSmng/TBNTBkFemHHHj5YY7VAU/MBU980F4VU1NG0= +github.com/cosmos/interchain-security/v3 v3.1.1-0.20231102122221-81650a84f989 h1:Yk/2X33hHuS0mqjr4rE0ShiwPE/YflXgdyXPIYdwl+Q= +github.com/cosmos/interchain-security/v3 v3.1.1-0.20231102122221-81650a84f989/go.mod h1:5B29fgUbUDTpBTqCnEzA2g3gI5rQG0YE/ir4isb2MEw= +github.com/cosmos/keyring v1.2.0 h1:8C1lBP9xhImmIabyXW4c3vFjjLiBdGCmfLUfeZlV1Yo= +github.com/cosmos/keyring v1.2.0/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= +github.com/cosmos/ledger-cosmos-go v0.13.3 h1:7ehuBGuyIytsXbd4MP43mLeoN2LTOEnk5nvue4rK+yM= +github.com/cosmos/ledger-cosmos-go v0.13.3/go.mod h1:HENcEP+VtahZFw38HZ3+LS3Iv5XV6svsnkk9vdJtLr8= +github.com/cosmos/rosetta-sdk-go v0.10.0 h1:E5RhTruuoA7KTIXUcMicL76cffyeoyvNybzUGSKFTcM= +github.com/cosmos/rosetta-sdk-go v0.10.0/go.mod h1:SImAZkb96YbwvoRkzSMQB6noNJXFgWl/ENIznEoYQI4= +github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creachadair/taskgroup v0.4.2 h1:jsBLdAJE42asreGss2xZGZ8fJra7WtwnHWeJFxv2Li8= +github.com/creachadair/taskgroup v0.4.2/go.mod h1:qiXUOSrbwAY3u0JPGTzObbE3yf9hcXHDKBZ2ZjpCbgM= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= +github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4= +github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= +github.com/decred/base58 v1.0.4 h1:QJC6B0E0rXOPA8U/kw2rP+qiRJsUaE2Er+pYb3siUeA= +github.com/decred/base58 v1.0.4/go.mod h1:jJswKPEdvpFpvf7dsDvFZyLT22xZ9lWqEByX38oGd9E= +github.com/decred/dcrd/chaincfg/chainhash v1.0.2 h1:rt5Vlq/jM3ZawwiacWjPa+smINyLRN07EO0cNBV6DGU= +github.com/decred/dcrd/chaincfg/chainhash v1.0.2/go.mod h1:BpbrGgrPTr3YJYRN3Bm+D9NuaFd+zGyNeIKgrhCXK60= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/dcrec/secp256k1/v2 v2.0.1 h1:18HurQ6DfHeNvwIjvOmrgr44bPdtVaQAe/WWwHg9goM= +github.com/decred/dcrd/dcrec/secp256k1/v2 v2.0.1/go.mod h1:XmyzkaXBy7ZvHdrTAlXAjpog8qKSAWa3ze7yqzWmgmc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= +github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= +github.com/dgraph-io/badger/v2 v2.2007.4 h1:TRWBQg8UrlUhaFdco01nO2uXwzKS7zd+HVdwV/GHc4o= +github.com/dgraph-io/badger/v2 v2.2007.4/go.mod h1:vSw/ax2qojzbN6eXHIx6KPKtCSHJN/Uz0X0VPruTIhk= +github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= +github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= +github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91 h1:Izz0+t1Z5nI16/II7vuEo/nHjodOg0p7+OiDpjX5t1E= +github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= +github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM= +github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf h1:Yt+4K30SdjOkRoRRm3vYNQgR+/ZIy0RmeUDZo7Y8zeQ= +github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/dvsekhvalnov/jose2go v1.6.0 h1:Y9gnSnP4qEI0+/uQkHvFXeD2PLPJeXEL+ySMEA2EjTY= +github.com/dvsekhvalnov/jose2go v1.6.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/emicklei/dot v1.6.1 h1:ujpDlBkkwgWUY+qPId5IwapRW/xEoligRSYjioR6DFI= +github.com/emicklei/dot v1.6.1/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= +github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= +github.com/faddat/go-substrate-rpc-client/v4 v4.0.1-0.20240402155230-48db8c110afe h1:63rMpjrCwbJVYoz1XFOzRXCZd8frLSuChg5XSo3tKg4= +github.com/faddat/go-substrate-rpc-client/v4 v4.0.1-0.20240402155230-48db8c110afe/go.mod h1:enTNfc1aCsOpHnOqlDEDAGr3SzacyTh/VX/nL+5YBs4= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= +github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= +github.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8= +github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= +github.com/go-kit/kit v0.13.0 h1:OoneCcHKHQ03LfBpoQCUfCluwd2Vt3ohz+kvbJneZAU= +github.com/go-kit/kit v0.13.0/go.mod h1:phqEHMMUbyrCFCTgH48JueqrM3md2HcAZ8N3XE4FKDg= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= +github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= +github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= +github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= +github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= +github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= +github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ= +github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= +github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= +github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/gobwas/ws v1.1.0 h1:7RFti/xnNkMJnrK7D1yQ/iCIB5OrrY/54/H930kIbHA= +github.com/gobwas/ws v1.1.0/go.mod h1:nzvNcVha5eUziGrbxFCo6qFIojQHjJV5cLYIbezhfL0= +github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk= +github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= +github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/googleapis v1.4.1-0.20201022092350-68b0159b7869/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= +github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0= +github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= +github.com/golang-jwt/jwt/v4 v4.3.0 h1:kHL1vqdqWNfATmA0FNMdmZNMyZI1U6O31X4rlIPoBog= +github.com/golang-jwt/jwt/v4 v4.3.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= +github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= +github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= +github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= +github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20230405160723-4a4c7d95572b h1:Qcx5LM0fSiks9uCyFZwDBUasd3lxd1RM0GYpL+Li5o4= +github.com/google/pprof v0.0.0-20230405160723-4a4c7d95572b/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= +github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= +github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= +github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= +github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= +github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= +github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= +github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= +github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= +github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= +github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= +github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= +github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= +github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= +github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= +github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= +github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= +github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is= +github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= +github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc= +github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= +github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-getter v1.7.5 h1:dT58k9hQ/vbxNMwoI5+xFYAJuv6152UNvdHokfI5wE4= +github.com/hashicorp/go-getter v1.7.5/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= +github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= +github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hdevalence/ed25519consensus v0.1.0 h1:jtBwzzcHuTmFrQN6xQZn6CQEO/V9f7HsjsjeEZ6auqU= +github.com/hdevalence/ed25519consensus v0.1.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo= +github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= +github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= +github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU= +github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= +github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= +github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= +github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= +github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= +github.com/iancoleman/orderedmap v0.2.0 h1:sq1N/TFpYH++aViPcaKjys3bDClUEU7s5B+z6jq8pNA= +github.com/iancoleman/orderedmap v0.2.0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/icza/dyno v0.0.0-20220812133438-f0b6f8a18845 h1:H+uM0Bv88eur3ZSsd2NGKg3YIiuXxwxtlN7HjE66UTU= +github.com/icza/dyno v0.0.0-20220812133438-f0b6f8a18845/go.mod h1:c1tRKs5Tx7E2+uHGSyyncziFjvGpgv4H2HrqXeUQ/Uk= +github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ= +github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPtwNr0l57L4f878wP8= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= +github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= +github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= +github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/kava-labs/cometbft v0.37.9-kava.1 h1:0mMsAhpV8p0peD9sabIZ//M4nP6LiiZ0o34gfuHdANY= +github.com/kava-labs/cometbft v0.37.9-kava.1/go.mod h1:j0Q3RqrCd+cztWCugs3obbzC4NyHGBPZZjtm/fWV00I= +github.com/kava-labs/cometbft-db v0.9.1-kava.2 h1:ZQaio886ifvml9XtJB4IYHhlArgA3+/a5Zwidg7H2J8= +github.com/kava-labs/cometbft-db v0.9.1-kava.2/go.mod h1:PvUZbx7zeR7I4CAvtKBoii/5ia5gXskKjDjIVpt7gDw= +github.com/kava-labs/cosmos-sdk v0.47.10-iavl-v1-kava.1 h1:vQwrm3sdAG1pkwrsi2mmCHSGDje5fzUR6vApEux/nVA= +github.com/kava-labs/cosmos-sdk v0.47.10-iavl-v1-kava.1/go.mod h1:OwLYEBcsnijCLE8gYkwQ7jycZZ/Acd+a83pJU+V+MKw= +github.com/kava-labs/ethermint v0.21.1-0.20240703152838-badab86e5aba h1:qrBo1h72L9WxZ7nUdpC7KlkTnscUfwWZAcZI1fWyMwE= +github.com/kava-labs/ethermint v0.21.1-0.20240703152838-badab86e5aba/go.mod h1:/Gxb9qs4shgPP2FQMvm2DkZ/7csmEGUh7F5vl7fKQZw= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= +github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= +github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= +github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= +github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= +github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= +github.com/libp2p/go-libp2p v0.27.8 h1:IX5x/4yKwyPQeVS2AXHZ3J4YATM9oHBGH1gBc23jBAI= +github.com/libp2p/go-libp2p v0.27.8/go.mod h1:eCFFtd0s5i/EVKR7+5Ki8bM7qwkNW3TPTTSSW9sz8NE= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/linxGnu/grocksdb v1.8.13 h1:X3Id7Obhf8qLY9WPc4LmmtIyabmdDf810XSFDnLlW7E= +github.com/linxGnu/grocksdb v1.8.13/go.mod h1:QYiYypR2d4v63Wj1adOOfzglnoII0gLj3PNh4fZkcFA= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= +github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= +github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= +github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= +github.com/mimoo/StrobeGo v0.0.0-20220103164710-9a04d6ca976b h1:QrHweqAtyJ9EwCaGHBu1fghwxIPiopAHV06JlXrMHjk= +github.com/mimoo/StrobeGo v0.0.0-20220103164710-9a04d6ca976b/go.mod h1:xxLb2ip6sSUts3g1irPVHyk/DGslwQsNOo9I7smJfNU= +github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= +github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= +github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= +github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= +github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae h1:O4SWKdcHVCvYqyDV+9CJA1fcDN2L11Bule0iFy3YlAI= +github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= +github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= +github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= +github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= +github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= +github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= +github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= +github.com/multiformats/go-multiaddr v0.9.0 h1:3h4V1LHIk5w4hJHekMKWALPXErDfz/sggzwC/NcqbDQ= +github.com/multiformats/go-multiaddr v0.9.0/go.mod h1:mI67Lb1EeTOYb8GQfL/7wpIZwc46ElrvzhYnoJOmTT0= +github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= +github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk= +github.com/multiformats/go-multicodec v0.8.1 h1:ycepHwavHafh3grIbR1jIXnKCsFm0fqsfEOsJ8NtKE8= +github.com/multiformats/go-multicodec v0.8.1/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI16i14xuaojr/H7Ai54k= +github.com/multiformats/go-multihash v0.2.1 h1:aem8ZT0VA2nCHHk7bPJ1BjUbHNciqZC/d16Vve9l108= +github.com/multiformats/go-multihash v0.2.1/go.mod h1:WxoMcYG85AZVQUyRyo9s4wULvW5qrI9vb2Lt6evduFc= +github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= +github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/grpc-proxy v0.0.0-20181017164139-0f1106ef9c76/go.mod h1:x5OoJHDHqxHS801UIuhqGl6QdSAEJvtausosHSdazIo= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/ginkgo/v2 v2.9.2 h1:BA2GMJOtfGAfagzYtrAlufIP0lq6QERkFmHLMLPwFSU= +github.com/onsi/ginkgo/v2 v2.9.2/go.mod h1:WHcJJG2dIlcCqVfBAwUCrJxSPFb6v4azBwgxeMeDuts= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= +github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= +github.com/opencontainers/runc v1.1.3 h1:vIXrkId+0/J2Ymu2m7VjGvbSlAId9XNRPhn2p4b+d8w= +github.com/opencontainers/runc v1.1.3/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= +github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= +github.com/oxyno-zeta/gomock-extra-matcher v1.1.0 h1:Yyk5ov0ZPKBXtVEeIWtc4J2XVrHuNoIK+0F2BUJgtsc= +github.com/oxyno-zeta/gomock-extra-matcher v1.1.0/go.mod h1:UMGTHYEmJ1dRq8LDZ7VTAYO4nqM3GD1UGC3RJEUxEz0= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= +github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= +github.com/petermattis/goid v0.0.0-20231207134359-e60b3f734c67 h1:jik8PHtAIsPlCRJjJzl4udgEf7hawInF9texMeO2jrU= +github.com/petermattis/goid v0.0.0-20231207134359-e60b3f734c67/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pierrec/xxHash v0.1.5 h1:n/jBpwTHiER4xYvK3/CdPVnLDPchj8eTJFFLUb4QHBo= +github.com/pierrec/xxHash v0.1.5/go.mod h1:w2waW5Zoa/Wc4Yqe0wgrIYAGKqRMf7czn2HNKXmuL+I= +github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= +github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= +github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= +github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.13.0 h1:GqzLlQyfsPbaEHaQkO7tbDlriv/4o5Hudv6OXHGKX7o= +github.com/prometheus/procfs v0.13.0/go.mod h1:cd4PFCR54QLnGKPaKGA6l+cfuNXtht43ZKY6tow0Y1g= +github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= +github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/regen-network/protobuf v1.3.3-alpha.regen.1 h1:OHEc+q5iIAXpqiqFKeLpu5NwTIkVXUs48vFMwzqpqY4= +github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC5sZ4OhQ3+NtdbZ6oBDKQwq5Ou+FI= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw= +github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= +github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/cors v1.8.3 h1:O+qNyWn7Z+F9M0ILBHgMVPuB1xTOucVd5gtaYyXBpRo= +github.com/rs/cors v1.8.3/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= +github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= +github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= +github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= +github.com/strangelove-ventures/interchaintest/v7 v7.0.1-0.20240506191732-71a15c29f2b7 h1:7Qsz/NHs+FqDHvjHB3qLIMU7+/Z8vPI8ZJ2Q0p7x93U= +github.com/strangelove-ventures/interchaintest/v7 v7.0.1-0.20240506191732-71a15c29f2b7/go.mod h1:J1Pbldeib6FKgQmEZvlaqvVNYDmQxVpR49KMBfMh8Z4= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= +github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= +github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= +github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= +github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI= +github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE= +github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= +github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= +github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= +github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli/v2 v2.10.2 h1:x3p8awjp/2arX+Nl/G2040AZpOCHS/eMJJ1/a+mye4Y= +github.com/urfave/cli/v2 v2.10.2/go.mod h1:f8iq5LtQ/bLxafbdBSLPPNsgaW0l/2fYYEHhAyPlwvo= +github.com/vedhavyas/go-subkey/v2 v2.0.0 h1:LemDIsrVtRSOkp0FA8HxP6ynfKjeOj3BY2U9UNfeDMA= +github.com/vedhavyas/go-subkey/v2 v2.0.0/go.mod h1:95aZ+XDCWAUUynjlmi7BtPExjXgXxByE0WfBwbmIRH4= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= +github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= +github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= +github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA= +go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 h1:UNQQKPfTDe1J81ViolILjTKPr9WetKW6uei2hFgJmFs= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0/go.mod h1:r9vWsPS/3AQItv3OSlEJ/E4mbrhUbbw18meOjArPtKQ= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 h1:sv9kVfal0MK0wBMCOGr+HeJm9v803BkJxGrk2au7j08= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0/go.mod h1:SK2UL73Zy1quvRPonmOmRDiWk1KBV3LyIeeIxcEApWw= +go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y= +go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= +go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg= +go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= +go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= +go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= +go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0= +go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= +go.uber.org/mock v0.2.0 h1:TaP3xedm7JaAgScZO7tlvlKrqT0p7I6OsdGB5YNSMDU= +go.uber.org/mock v0.2.0/go.mod h1:J0y0rp9L3xiff1+ZBfKxlC1fz2+aO16tw0tsDOixfuM= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20230711153332-06a737ee72cb h1:xIApU0ow1zwMa2uL1VDNeQlNVFTWMQxZUZCMDy0Q4Us= +golang.org/x/exp v0.0.0-20230711153332-06a737ee72cb/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= +golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= +golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ= +golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= +golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= +golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY= +golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= +google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= +google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= +google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= +google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= +google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= +google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= +google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= +google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= +google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= +google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= +google.golang.org/api v0.77.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= +google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= +google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= +google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= +google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6FO2g= +google.golang.org/api v0.90.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= +google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= +google.golang.org/api v0.95.0/go.mod h1:eADj+UBuxkh5zlrSntJghuNeg8HwQ1w5lTKkuqaETEI= +google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= +google.golang.org/api v0.162.0 h1:Vhs54HkaEpkMBdgGdOT2P6F0csGG/vxDS0hWHJzmmps= +google.golang.org/api v0.162.0/go.mod h1:6SulDkfoBIg4NFmCuZ39XeeAgSHCPecfSUuDyYlAHs0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200324203455-a04cca1dde73/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220722212130-b98a9ff5e252/go.mod h1:GkXuJDJ6aQ7lnJcRF+SJVgFdQhypqgl3LB1C9vabdRE= +google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc= +google.golang.org/genproto v0.0.0-20220815135757-37a418bb8959/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220817144833-d7fd3f11b9b1/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220829144015-23454907ede3/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220829175752-36a9c930ecbf/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220913154956-18f8339a66a5/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220914142337-ca0e39ece12f/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220915135415-7fd63a7952de/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220916172020-2692e8806bfa/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220919141832-68c03719ef51/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006/go.mod h1:ht8XFiar2npT/g4vkk7O0WYS1sHOHbdujxbEp7CJWbw= +google.golang.org/genproto v0.0.0-20220926165614-551eb538f295/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= +google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= +google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U= +google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= +google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= +google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= +google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0= +google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= +google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= +gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= +lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0= +lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA= +lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI= +lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw= +modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0= +modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw= +modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY= +modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk= +modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= +modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM= +modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= +modernc.org/libc v1.24.1 h1:uvJSeCKL/AgzBo2yYIPPTy82v21KgGnizcGYfBHaNuM= +modernc.org/libc v1.24.1/go.mod h1:FmfO1RLrU3MHJfyi9eYYmZBfi/R+tqZ6+hQ3yQQUkak= +modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ= +modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/memory v1.6.0 h1:i6mzavxrE9a30whzMfwf7XWVODx2r5OYXvU46cirX7o= +modernc.org/memory v1.6.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= +modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= +modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/sqlite v1.25.0 h1:AFweiwPNd/b3BoKnBOfFm+Y260guGMF+0UFk0savqeA= +modernc.org/sqlite v1.25.0/go.mod h1:FL3pVXie73rg3Rii6V/u5BoHlSoyeZeIgKZEgHARyCU= +modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY= +modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= +modernc.org/tcl v1.15.2 h1:C4ybAYCGJw968e+Me18oW55kD/FexcHbqH2xak1ROSY= +modernc.org/tcl v1.15.2/go.mod h1:3+k/ZaEbKrC8ePv8zJWPtBSW0V7Gg9g8rkmhI1Kfs3c= +modernc.org/token v1.0.1 h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg= +modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/z v1.7.3 h1:zDJf6iHjrnB+WRD88stbXokugjyc0/pB91ri1gO6LZY= +modernc.org/z v1.7.3/go.mod h1:Ipv4tsdxZRbQyLq9Q1M6gdbkxYzdlrciF2Hi/lS7nWE= +nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= +nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= +nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= +pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw= +pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/tests/e2e-ibc/main_test.go b/tests/e2e-ibc/main_test.go new file mode 100644 index 00000000..8d24769a --- /dev/null +++ b/tests/e2e-ibc/main_test.go @@ -0,0 +1,206 @@ +package main_test + +import ( + "context" + "fmt" + "testing" + "time" + + "cosmossdk.io/math" + transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/strangelove-ventures/interchaintest/v7" + "github.com/strangelove-ventures/interchaintest/v7/chain/cosmos" + "github.com/strangelove-ventures/interchaintest/v7/ibc" + "github.com/strangelove-ventures/interchaintest/v7/testreporter" + + "github.com/stretchr/testify/require" + "go.uber.org/zap/zaptest" + + kavainterchain "github.com/kava-labs/kava/tests/interchain" +) + +func TestInterchainIBC(t *testing.T) { + ctx := context.Background() + + // setup chains + cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{ + {Name: "kava", ChainConfig: kavainterchain.DefaultKavaChainConfig(kavainterchain.KavaTestChainId)}, + {Name: "gaia", Version: "v15.2.0", ChainConfig: ibc.ChainConfig{GasPrices: "0.0uatom"}}, + {Name: "osmosis", Version: "v24.0.1"}, + }) + + chains, err := cf.Chains(t.Name()) + require.NoError(t, err) + + kava, gaia, osmosis := chains[0].(*cosmos.CosmosChain), chains[1].(*cosmos.CosmosChain), chains[2].(*cosmos.CosmosChain) + + // setup relayer + client, network := interchaintest.DockerSetup(t) + r := interchaintest.NewBuiltinRelayerFactory(ibc.CosmosRly, zaptest.NewLogger(t)). + Build(t, client, network) + + // configure interchain + const kavaGaiaIbcPath = "kava-gaia-demo" + const kavaOsmosisIbcPath = "kava-osmo-demo" + ic := interchaintest.NewInterchain(). + AddChain(kava). + AddChain(gaia). + AddChain(osmosis). + AddRelayer(r, "relayer"). + AddLink(interchaintest.InterchainLink{ + Chain1: kava, + Chain2: gaia, + Relayer: r, + Path: kavaGaiaIbcPath, + }). + AddLink(interchaintest.InterchainLink{ + Chain1: kava, + Chain2: osmosis, + Relayer: r, + Path: kavaOsmosisIbcPath, + }) + + // Log location + f, err := interchaintest.CreateLogFile(fmt.Sprintf("%d.json", time.Now().Unix())) + require.NoError(t, err) + // Reporter/logs + rep := testreporter.NewReporter(f) + eRep := rep.RelayerExecReporter(t) + + // Build interchain + err = ic.Build(ctx, eRep, interchaintest.InterchainBuildOptions{ + TestName: t.Name(), + Client: client, + NetworkID: network, + SkipPathCreation: false}, + ) + require.NoError(t, err) + + // start the relayer so we don't need to manually Flush() packets + err = r.StartRelayer(ctx, eRep, kavaGaiaIbcPath, kavaOsmosisIbcPath) + require.NoError(t, err) + defer r.StopRelayer(ctx, eRep) + + // Create and Fund User Wallets + fundAmount := math.NewInt(10_000_000) + + users := interchaintest.GetAndFundTestUsers(t, ctx, "default", fundAmount, kava, gaia, osmosis) + kavaUser := users[0] + gaiaUser := users[1] + osmosisUser := users[2] + + // wait for new block to ensure initial funding complete + height, err := kava.Height(ctx) + require.NoError(t, err) + h := height + for h <= height { + h, err = kava.Height(ctx) + require.NoError(t, err) + } + + // check initial balance + kavaUserBalInitial, err := kava.GetBalance(ctx, kavaUser.FormattedAddress(), kava.Config().Denom) + require.NoError(t, err) + require.True(t, kavaUserBalInitial.Equal(fundAmount)) + + // get ibc channel ids + gaiaChannelInfo, err := r.GetChannels(ctx, eRep, gaia.Config().ChainID) + require.NoError(t, err) + osmoChannelInfo, err := r.GetChannels(ctx, eRep, osmosis.Config().ChainID) + require.NoError(t, err) + + gaiaToKavaChannelID := gaiaChannelInfo[0].ChannelID + kavaToGaiaChannelID := gaiaChannelInfo[0].Counterparty.ChannelID + osmoToKavaChannelID := osmoChannelInfo[0].ChannelID + kavaToOsmoChannelID := osmoChannelInfo[0].Counterparty.ChannelID + + // determine ibc denoms + srcDenomTrace := transfertypes.ParseDenomTrace(transfertypes.GetPrefixedDenom("transfer", gaiaToKavaChannelID, kava.Config().Denom)) + kavaOnGaiaDenom := srcDenomTrace.IBCDenom() + srcDenomTrace = transfertypes.ParseDenomTrace(transfertypes.GetPrefixedDenom("transfer", osmoToKavaChannelID, kava.Config().Denom)) + kavaOnOsmoDenom := srcDenomTrace.IBCDenom() + + amountToSend := math.NewInt(1_000_000) + + // IBC transfer kava to cosmoshub + // inspired by https://github.com/strangelove-ventures/interchaintest/blob/main/examples/ibc/learn_ibc_test.go + t.Run("ibc transfer kava -> cosmoshub", func(t *testing.T) { + dstAddress := gaiaUser.FormattedAddress() + transfer := ibc.WalletAmount{ + Address: dstAddress, + Denom: kava.Config().Denom, + Amount: amountToSend, + } + + tx, err := kava.SendIBCTransfer(ctx, kavaToGaiaChannelID, kavaUser.KeyName(), transfer, ibc.TransferOptions{}) + require.NoError(t, err) + require.NoError(t, tx.Validate()) + + // manually flush packets so we don't need to wait for the relayer + require.NoError(t, r.Flush(ctx, eRep, kavaGaiaIbcPath, kavaToGaiaChannelID)) + + // verify balance deducted from kava account + expectedBal := kavaUserBalInitial.Sub(amountToSend) + kavaUserBalNew, err := kava.GetBalance(ctx, kavaUser.FormattedAddress(), kava.Config().Denom) + require.NoError(t, err) + require.True(t, kavaUserBalNew.Equal(expectedBal)) + + // verify cosmoshub account received funds + gaiaUserBalNew, err := gaia.GetBalance(ctx, gaiaUser.FormattedAddress(), kavaOnGaiaDenom) + require.NoError(t, err) + require.True(t, gaiaUserBalNew.Equal(amountToSend)) + }) + + // use coins IBC'd to cosmoshub, send them to osmosis using pfm + t.Run("packet forwarding middleware: cosmoshub -> kava -> osmosis", func(t *testing.T) { + dstAddress := osmosisUser.FormattedAddress() + transfer := ibc.WalletAmount{ + Address: "pfm", // purposefully invalid b/c we are forwarding through kava onward to osmosis! + Denom: kavaOnGaiaDenom, + Amount: amountToSend, + } + + tx, err := gaia.SendIBCTransfer(ctx, gaiaToKavaChannelID, gaiaUser.KeyName(), transfer, ibc.TransferOptions{ + // packet forwarding middleware! + Memo: fmt.Sprintf(`{ + "forward": { + "receiver": "%s", + "port": "transfer", + "channel": "%s" + } + }`, dstAddress, kavaToOsmoChannelID), + }) + require.NoError(t, err) + require.NoError(t, tx.Validate()) + + require.Eventually(t, func() bool { + // verify transfer to osmosis + osmosisUserBalNew, err := osmosis.GetBalance(ctx, osmosisUser.FormattedAddress(), kavaOnOsmoDenom) + require.NoError(t, err) + return osmosisUserBalNew.Equal(amountToSend) + }, 15*time.Second, time.Second, "osmosis never received funds") + + // verify cosmoshub account no longer has the funds + gaiaUserBalNew, err := gaia.GetBalance(ctx, gaiaUser.FormattedAddress(), kavaOnGaiaDenom) + require.NoError(t, err) + require.True(t, gaiaUserBalNew.Equal(math.ZeroInt())) + }) + + t.Run("query evm data", func(t *testing.T) { + evmUrl, err := kava.FullNodes[0].GetHostAddress(ctx, "8545/tcp") + require.NoError(t, err) + + evmClient, err := ethclient.Dial(evmUrl) + require.NoError(t, err, "failed to connect to evm") + + bal, err := evmClient.BalanceAt(ctx, common.BytesToAddress(kavaUser.Address()), nil) + require.NoError(t, err) + + // convert ukava to akava + expected := fundAmount.Sub(amountToSend).MulRaw(1e12) + require.Equal(t, expected.BigInt().String(), bal.String()) + }) +} diff --git a/tests/e2e/.env b/tests/e2e/.env index 8c757f08..966c5d10 100644 --- a/tests/e2e/.env +++ b/tests/e2e/.env @@ -21,12 +21,12 @@ E2E_SKIP_SHUTDOWN=false # E2E_INCLUDE_AUTOMATED_UPGRADE when true enables the automated upgrade & corresponding tests in the suite. E2E_INCLUDE_AUTOMATED_UPGRADE=true # E2E_KAVA_UPGRADE_NAME is the name of the upgrade that must be in the current local image. -E2E_KAVA_UPGRADE_NAME=v0.26.0 +E2E_KAVA_UPGRADE_NAME=v0.27.0 # E2E_KAVA_UPGRADE_HEIGHT is the height at which the upgrade will be applied. # If IBC tests are enabled this should be >30. Otherwise, this should be >10. E2E_KAVA_UPGRADE_HEIGHT=35 # E2E_KAVA_UPGRADE_BASE_IMAGE_TAG is the tag of the docker image the chain should upgrade from. -E2E_KAVA_UPGRADE_BASE_IMAGE_TAG=v0.25.1-goleveldb +E2E_KAVA_UPGRADE_BASE_IMAGE_TAG=v0.26.0-goleveldb # E2E_KAVA_ERC20_ADDRESS is the address of a pre-deployed ERC20 token with the following properties: # - the E2E_KAVA_FUNDED_ACCOUNT_MNEMONIC has nonzero balance diff --git a/tests/e2e/e2e_upgrade_handler_test.go b/tests/e2e/e2e_upgrade_handler_test.go index 4d79ddcb..71e4263e 100644 --- a/tests/e2e/e2e_upgrade_handler_test.go +++ b/tests/e2e/e2e_upgrade_handler_test.go @@ -1,127 +1,102 @@ package e2e_test import ( - "time" - - tmproto "github.com/cometbft/cometbft/proto/tendermint/types" - tmtypes "github.com/cometbft/cometbft/types" - sdk "github.com/cosmos/cosmos-sdk/types" - consensustypes "github.com/cosmos/cosmos-sdk/x/consensus/types" - govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1" + precisebanktypes "github.com/0glabs/0g-chain/x/precisebank/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) -func (suite *IntegrationTestSuite) TestUpgradeParams_SDK() { +func (suite *IntegrationTestSuite) TestUpgrade_PreciseBankReserveTransfer() { suite.SkipIfUpgradeDisabled() beforeUpgradeCtx := suite.ZgChain.Grpc.CtxAtHeight(suite.UpgradeHeight - 1) afterUpgradeCtx := suite.ZgChain.Grpc.CtxAtHeight(suite.UpgradeHeight) - // Before params grpcClient := suite.ZgChain.Grpc - govParamsBefore, err := grpcClient.Query.Gov.Params(beforeUpgradeCtx, &govtypes.QueryParamsRequest{ - ParamsType: govtypes.ParamDeposit, - }) - suite.NoError(err) - govParamsAfter, err := grpcClient.Query.Gov.Params(afterUpgradeCtx, &govtypes.QueryParamsRequest{ - ParamsType: govtypes.ParamDeposit, - }) - suite.NoError(err) - // after upgrade, querying params before upgrade height returns nil - // since the param gprc query no longer queries x/params - suite.Run("x/gov parameters before upgrade", func() { - suite.Assert().Nil( - govParamsBefore.DepositParams.MaxDepositPeriod, - "x/gov DepositParams max deposit period before upgrade should be nil", - ) - suite.Assert().Nil( - govParamsBefore.DepositParams.MinDeposit, - "x/gov DepositParams min deposit before upgrade should be 10_000_000 ukava", - ) - }) + // ----------------------------- + // Get initial reserve balances + evmutilAddr := "kava1w9vxuke5dz6hyza2j932qgmxltnfxwl78u920k" + precisebankAddr := "kava12yfe2jaupmtjruwxsec7hg7er60fhaa4uz7ffl" - suite.Run("x/gov parameters after upgrade", func() { - suite.Assert().Equal( - mustParseDuration("172800s"), - govParamsAfter.DepositParams.MaxDepositPeriod, - "x/gov DepositParams max deposit period after upgrade should be 172800s", - ) - suite.Assert().Equal( - []sdk.Coin{{Denom: "ua0gi", Amount: sdk.NewInt(10_000_000)}}, - govParamsAfter.DepositParams.MinDeposit, - "x/gov DepositParams min deposit after upgrade should be 10_000_000 ukava", - ) - - expectedParams := govtypes.Params{ - MinDeposit: sdk.NewCoins(sdk.NewCoin("ua0gi", sdk.NewInt(10_000_000))), - MaxDepositPeriod: mustParseDuration("172800s"), - VotingPeriod: mustParseDuration("30s"), - Quorum: "0.334000000000000000", - Threshold: "0.500000000000000000", - VetoThreshold: "0.334000000000000000", - MinInitialDepositRatio: "0.000000000000000000", - BurnVoteQuorum: false, - BurnProposalDepositPrevote: false, - BurnVoteVeto: true, - } - suite.Require().Equal(expectedParams, *govParamsAfter.Params, "x/gov params after upgrade should be as expected") + previousEvmutilBalRes, err := grpcClient.Query.Bank.Balance(beforeUpgradeCtx, &banktypes.QueryBalanceRequest{ + Address: evmutilAddr, + Denom: precisebanktypes.IntegerCoinDenom, }) -} - -func (suite *IntegrationTestSuite) TestUpgradeParams_Consensus() { - suite.SkipIfUpgradeDisabled() - - afterUpgradeCtx := suite.ZgChain.Grpc.CtxAtHeight(suite.UpgradeHeight) - - grpcClient := suite.ZgChain.Grpc - paramsAfter, err := grpcClient.Query.Consensus.Params(afterUpgradeCtx, &consensustypes.QueryParamsRequest{}) - suite.NoError(err) - - // v25 consensus params from x/params should be migrated to x/consensus - expectedParams := tmproto.ConsensusParams{ - Block: &tmproto.BlockParams{ - MaxBytes: 22020096, - MaxGas: 20000000, - }, - Evidence: &tmproto.EvidenceParams{ - MaxAgeNumBlocks: 100000, - MaxAgeDuration: *mustParseDuration("172800s"), - MaxBytes: 1048576, - }, - Validator: &tmproto.ValidatorParams{ - PubKeyTypes: []string{ - tmtypes.ABCIPubKeyTypeEd25519, - }, - }, - Version: nil, - } - suite.Require().Equal(expectedParams, *paramsAfter.Params, "x/consensus params after upgrade should be as expected") -} - -// func (suite *IntegrationTestSuite) TestUpgradeParams_CDP_Interval() { -// suite.SkipIfUpgradeDisabled() - -// beforeUpgradeCtx := suite.Kava.Grpc.CtxAtHeight(suite.UpgradeHeight - 1) -// afterUpgradeCtx := suite.Kava.Grpc.CtxAtHeight(suite.UpgradeHeight) - -// grpcClient := suite.Kava.Grpc - -// paramsBefore, err := grpcClient.Query.Cdp.Params(beforeUpgradeCtx, &cdptypes.QueryParamsRequest{}) -// suite.Require().NoError(err) -// paramsAfter, err := grpcClient.Query.Cdp.Params(afterUpgradeCtx, &cdptypes.QueryParamsRequest{}) -// suite.Require().NoError(err) - -// expectedParams := paramsBefore.Params -// expectedParams.LiquidationBlockInterval = int64(50) - -// suite.Require().Equal(expectedParams, paramsAfter.Params, -// "expected cdp parameters to equal previous parameters with a liquidation block interval of 100") -// } - -func mustParseDuration(s string) *time.Duration { - d, err := time.ParseDuration(s) - if err != nil { - panic(err) - } - return &d + suite.Require().NoError(err) + suite.Require().NotNil(previousEvmutilBalRes.Balance) + suite.Require().True( + previousEvmutilBalRes.Balance.Amount.IsPositive(), + "should have reserve balance before upgrade", + ) + + previousPrecisebankBalRes, err := grpcClient.Query.Bank.Balance(beforeUpgradeCtx, &banktypes.QueryBalanceRequest{ + Address: precisebankAddr, + Denom: precisebanktypes.IntegerCoinDenom, + }) + suite.Require().NoError(err) + suite.Require().NotNil(previousPrecisebankBalRes.Balance) + suite.Require().True( + previousPrecisebankBalRes.Balance.Amount.IsZero(), + "should be empty before upgrade", + ) + + suite.T().Logf("x/evmutil balances before upgrade: %s", previousEvmutilBalRes.Balance) + suite.T().Logf("x/precisebank balances before upgrade: %s", previousPrecisebankBalRes.Balance) + + // ----------------------------- + // After upgrade + // - Check reserve balance transfer + // - Check reserve fully backs fractional amounts + afterEvmutilBalRes, err := grpcClient.Query.Bank.Balance(afterUpgradeCtx, &banktypes.QueryBalanceRequest{ + Address: evmutilAddr, + Denom: precisebanktypes.IntegerCoinDenom, + }) + suite.Require().NoError(err) + suite.Require().NotNil(afterEvmutilBalRes.Balance) + suite.Require().Truef( + afterEvmutilBalRes.Balance.Amount.IsZero(), + "should have transferred all reserve balance to precisebank, expected 0 but got %s", + afterEvmutilBalRes.Balance, + ) + + afterPrecisebankBalRes, err := grpcClient.Query.Bank.Balance(afterUpgradeCtx, &banktypes.QueryBalanceRequest{ + Address: precisebankAddr, + Denom: precisebanktypes.IntegerCoinDenom, + }) + suite.Require().NoError(err) + suite.Require().NotNil(afterPrecisebankBalRes.Balance) + // 2 total in reserve- genesis.json has 5 accounts with fractional balances + // totalling 2 integer coins + suite.Require().Equal(int64(2), afterPrecisebankBalRes.Balance.Amount.Int64()) + + suite.T().Logf("x/evmutil balances after upgrade: %s", afterEvmutilBalRes.Balance) + suite.T().Logf("x/precisebank balances after upgrade: %s", afterPrecisebankBalRes.Balance) + + sumFractional, err := grpcClient.Query.Precisebank.TotalFractionalBalances( + afterUpgradeCtx, + &precisebanktypes.QueryTotalFractionalBalancesRequest{}, + ) + suite.Require().NoError(err) + + suite.Require().Equal( + sumFractional.Total.Amount, + afterPrecisebankBalRes.Balance.Amount.Mul(precisebanktypes.ConversionFactor()), + "reserve should match exactly sum fractional balances", + ) + + // Check remainder + total fractional balances = reserve balance + remainderRes, err := grpcClient.Query.Precisebank.Remainder( + afterUpgradeCtx, + &precisebanktypes.QueryRemainderRequest{}, + ) + suite.Require().NoError(err) + + sumFractionalAndRemainder := sumFractional.Total.Add(remainderRes.Remainder) + reserveBalanceExtended := afterPrecisebankBalRes.Balance.Amount.Mul(precisebanktypes.ConversionFactor()) + + suite.Require().Equal( + sumFractionalAndRemainder.Amount, + reserveBalanceExtended, + "remainder + sum(fractional balances) should be = reserve balance", + ) } diff --git a/tests/e2e/kvtool b/tests/e2e/kvtool index 79bb25f4..f78c7454 160000 --- a/tests/e2e/kvtool +++ b/tests/e2e/kvtool @@ -1 +1 @@ -Subproject commit 79bb25f47d20c10e70f0539c519240fba82b3302 +Subproject commit f78c74549f62d975d8de99c7bd158b3d92e5b145 diff --git a/tests/e2e/testutil/account.go b/tests/e2e/testutil/account.go index 5e5659aa..5c29656d 100644 --- a/tests/e2e/testutil/account.go +++ b/tests/e2e/testutil/account.go @@ -13,11 +13,9 @@ import ( sdkmath "cosmossdk.io/math" "github.com/cosmos/cosmos-sdk/crypto/hd" - "github.com/cosmos/cosmos-sdk/crypto/types" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - "github.com/cosmos/go-bip39" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" @@ -208,17 +206,15 @@ func (a *SigningAccount) SignAndBroadcastEvmTx(req util.EvmTxRequest) EvmTxRespo // SignRawEvmData signs raw evm data with the SigningAccount's private key. // It does not broadcast the signed data. -func (a *SigningAccount) SignRawEvmData(msg []byte) ([]byte, types.PubKey, error) { +func (a *SigningAccount) SignRawEvmData(msg []byte) ([]byte, cryptotypes.PubKey, error) { keyringSigner := emtests.NewSigner(a.evmPrivKey) return keyringSigner.SignByAddress(a.SdkAddress, msg) } // NewFundedAccount creates a SigningAccount for a random account & funds the account from the whale. func (chain *Chain) NewFundedAccount(name string, funds sdk.Coins) *SigningAccount { - entropy, err := bip39.NewEntropy(128) - require.NoErrorf(chain.t, err, "failed to generate entropy for account %s: %s", name, err) - mnemonic, err := bip39.NewMnemonic(entropy) - require.NoErrorf(chain.t, err, "failed to create new mnemonic for account %s: %s", name, err) + mnemonic, err := util.RandomMnemonic() + require.NoError(chain.t, err) acc := chain.AddNewSigningAccount( name, diff --git a/tests/e2e/testutil/suite.go b/tests/e2e/testutil/suite.go index 80c299fe..bc656cca 100644 --- a/tests/e2e/testutil/suite.go +++ b/tests/e2e/testutil/suite.go @@ -217,7 +217,7 @@ func (suite *E2eTestSuite) SkipIfIbcDisabled() { } // SkipIfUpgradeDisabled should be called at the start of tests that require automated upgrades. -// It gracefully skips the current test if upgrades are dissabled. +// It gracefully skips the current test if upgrades are disabled. // Note: automated upgrade tests are currently only enabled for Kvtool suite runs. func (suite *E2eTestSuite) SkipIfUpgradeDisabled() { if suite.config.Kvtool != nil && !suite.config.Kvtool.IncludeAutomatedUpgrade { diff --git a/tests/util/addresses.go b/tests/util/addresses.go index d8118d41..c0063828 100644 --- a/tests/util/addresses.go +++ b/tests/util/addresses.go @@ -1,7 +1,9 @@ package util import ( + errorsmod "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/go-bip39" "github.com/ethereum/go-ethereum/common" ) @@ -12,3 +14,12 @@ func SdkToEvmAddress(addr sdk.AccAddress) common.Address { func EvmToSdkAddress(addr common.Address) sdk.AccAddress { return sdk.AccAddress(addr.Bytes()) } + +// RandomMnemonic generates a random BIP39 mnemonic from 128 bits of entropy +func RandomMnemonic() (string, error) { + entropy, err := bip39.NewEntropy(128) + if err != nil { + return "", errorsmod.Wrap(err, "failed to generate entropy for new mnemonic") + } + return bip39.NewMnemonic(entropy) +} diff --git a/tests/util/evmsigner.go b/tests/util/evmsigner.go index 5b860ef9..9bb4fd80 100644 --- a/tests/util/evmsigner.go +++ b/tests/util/evmsigner.go @@ -3,17 +3,21 @@ package util import ( "context" "crypto/ecdsa" + "encoding/hex" "errors" "fmt" "math/big" "time" + errorsmod "cosmossdk.io/errors" + "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" + "github.com/evmos/ethermint/crypto/ethsecp256k1" ) var ( @@ -77,6 +81,21 @@ func NewEvmSigner( }, nil } +func NewEvmSignerFromMnemonic(evmClient *ethclient.Client, evmChainId *big.Int, mnemonic string) (*EvmSigner, error) { + hdPath := hd.CreateHDPath(60, 0, 0) + privKeyBytes, err := hd.Secp256k1.Derive()(mnemonic, "", hdPath.String()) + if err != nil { + return nil, errorsmod.Wrap(err, "failed to derive private key from mnemonic") + } + privKey := ðsecp256k1.PrivKey{Key: privKeyBytes} + ecdsaPrivKey, err := crypto.HexToECDSA(hex.EncodeToString(privKey.Bytes())) + if err != nil { + return nil, err + } + + return NewEvmSigner(evmClient, ecdsaPrivKey, evmChainId) +} + func (s *EvmSigner) Run(requests <-chan EvmTxRequest) <-chan EvmTxResponse { responses := make(chan EvmTxResponse) diff --git a/tests/util/sdksigner.go b/tests/util/sdksigner.go index d3473145..db364917 100644 --- a/tests/util/sdksigner.go +++ b/tests/util/sdksigner.go @@ -358,7 +358,7 @@ func (s *ZgChainSigner) Run(requests <-chan ZgChainMsgRequest) (<-chan ZgChainMs currentRequest = nil } - // immediatley response to channel + // immediately response to channel responses <- *response // go to next request broadcastTxSeq++ diff --git a/third_party/proto/cosmos_proto/cosmos.proto b/third_party/proto/cosmos_proto/cosmos.proto index 5c63b86f..4fb58159 100644 --- a/third_party/proto/cosmos_proto/cosmos.proto +++ b/third_party/proto/cosmos_proto/cosmos.proto @@ -5,6 +5,12 @@ import "google/protobuf/descriptor.proto"; option go_package = "github.com/cosmos/cosmos-proto;cosmos_proto"; +extend google.protobuf.MethodOptions { + + // method_added_in is used to indicate from which version the method was added. + string method_added_in = 93001; +} + extend google.protobuf.MessageOptions { // implements_interface is used to indicate the type name of the interface @@ -13,6 +19,9 @@ extend google.protobuf.MessageOptions { // interfaces. Interfaces should be declared using a declare_interface // file option. repeated string implements_interface = 93001; + + // message_added_in is used to indicate from which version the message was added. + string message_added_in = 93002; } extend google.protobuf.FieldOptions { @@ -27,6 +36,9 @@ extend google.protobuf.FieldOptions { // generators may choose to use this information to map this field to a // language-specific type representing the scalar. string scalar = 93002; + + // field_added_in is used to indicate from which version the field was added. + string field_added_in = 93003; } extend google.protobuf.FileOptions { @@ -46,6 +58,9 @@ extend google.protobuf.FileOptions { // expected that the declaration will be found in a protobuf file named // a/b/scalars.proto in the file descriptor set. repeated ScalarDescriptor declare_scalar = 793022; + + // file_added_in is used to indicate from which the version the file was added. + string file_added_in = 793023; } // InterfaceDescriptor describes an interface type to be used with @@ -94,4 +109,4 @@ enum ScalarType { SCALAR_TYPE_UNSPECIFIED = 0; SCALAR_TYPE_STRING = 1; SCALAR_TYPE_BYTES = 2; -} +} \ No newline at end of file diff --git a/third_party/proto/ethermint/evm/v1/evm.proto b/third_party/proto/ethermint/evm/v1/evm.proto index 875619ff..43b3e7a5 100644 --- a/third_party/proto/ethermint/evm/v1/evm.proto +++ b/third_party/proto/ethermint/evm/v1/evm.proto @@ -18,12 +18,17 @@ message Params { repeated int64 extra_eips = 4 [(gogoproto.customname) = "ExtraEIPs", (gogoproto.moretags) = "yaml:\"extra_eips\""]; // chain_config defines the EVM chain configuration parameters ChainConfig chain_config = 5 [(gogoproto.moretags) = "yaml:\"chain_config\"", (gogoproto.nullable) = false]; - // list of allowed eip712 msgs and their types + // eip712_allowed_msgs contains list of allowed eip712 msgs and their types repeated EIP712AllowedMsg eip712_allowed_msgs = 6 [(gogoproto.customname) = "EIP712AllowedMsgs", (gogoproto.nullable) = false]; // allow_unprotected_txs defines if replay-protected (i.e non EIP155 // signed) transactions can be executed on the state machine. bool allow_unprotected_txs = 7; + // enabled_precompiles contains list of hex-encoded evm addresses of enabled precompiled contracts. + // Precompile must be registered before it can be enabled. + // enabled_precompiles should be sorted in ascending order and unique. + // sorting and uniqueness are checked against bytes representation of addresses + repeated string enabled_precompiles = 8; } // ChainConfig defines the Ethereum ChainConfig parameters using *sdk.Int values @@ -246,20 +251,20 @@ message TraceConfig { // EIP712AllowedMsg stores an allowed legacy msg and its eip712 type. message EIP712AllowedMsg { - // msg's proto type name. ie "/cosmos.bank.v1beta1.MsgSend" + // msg_type_url is a msg's proto type name. ie "/cosmos.bank.v1beta1.MsgSend" string msg_type_url = 1; - // name of the eip712 value type. ie "MsgValueSend" + // msg_value_type_name is a name of the eip712 value type. ie "MsgValueSend" string msg_value_type_name = 2; - // types of the msg value + // value_types is a list of msg value types repeated EIP712MsgAttrType value_types = 3 [(gogoproto.nullable) = false]; - // nested types of the msg value + // nested_types is a list of msg value nested types repeated EIP712NestedMsgType nested_types = 4 [(gogoproto.nullable) = false]; } -// EIP712MsgType is the eip712 type of a single message. +// EIP712NestedMsgType is the eip712 type of a single message. message EIP712NestedMsgType { // name of the nested type. ie "Fee", "Coin" string name = 1; @@ -270,6 +275,8 @@ message EIP712NestedMsgType { // EIP712MsgAttrType is the eip712 type of a single message attribute. message EIP712MsgAttrType { + // name string name = 1; + // type string type = 2; } diff --git a/x/bep3/abci_test.go b/x/bep3/abci_test.go index 0b15cb89..23d6448e 100644 --- a/x/bep3/abci_test.go +++ b/x/bep3/abci_test.go @@ -132,7 +132,7 @@ func (suite *ABCITestSuite) TestBeginBlocker_UpdateExpiredAtomicSwaps() { // Run the second begin blocker bep3.BeginBlocker(tc.secondCtx, suite.keeper) - // Check each swap's availibility and status + // Check each swap's availability and status for _, swapID := range suite.swapIDs { storedSwap, found := suite.keeper.GetAtomicSwap(tc.secondCtx, swapID) if tc.expectInStorage { diff --git a/x/bep3/keeper/asset_test.go b/x/bep3/keeper/asset_test.go index 6fd33023..f68f5e1a 100644 --- a/x/bep3/keeper/asset_test.go +++ b/x/bep3/keeper/asset_test.go @@ -431,7 +431,7 @@ func (suite *AssetTestSuite) TestIncrementOutgoingAssetSupply() { true, }, { - "outoing + amount > current", + "outgoing + amount > current", args{ coin: c("bnb", 36), }, diff --git a/x/bep3/types/swap.go b/x/bep3/types/swap.go index d5203223..aff0c50f 100644 --- a/x/bep3/types/swap.go +++ b/x/bep3/types/swap.go @@ -67,7 +67,7 @@ func (a AtomicSwap) Validate() error { if a.Recipient.Empty() { return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "recipient cannot be empty") } - // NOTE: These adresses may not have a bech32 prefix. + // NOTE: These addresses may not have a bech32 prefix. if strings.TrimSpace(a.SenderOtherChain) == "" { return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "sender other chain cannot be blank") } diff --git a/x/committee/keeper/proposal.go b/x/committee/keeper/proposal.go index f1d922f9..b5307206 100644 --- a/x/committee/keeper/proposal.go +++ b/x/committee/keeper/proposal.go @@ -185,7 +185,7 @@ func (k Keeper) GetTokenCommitteeProposalResult(ctx sdk.Context, proposalID uint return false } -// TallyMemberCommitteeVotes returns the polling status of a token committee vote. Returns yes votes, +// TallyTokenCommitteeVotes returns the polling status of a token committee vote. Returns yes votes, // total current votes, total possible votes (equal to token supply), vote threshold (yes vote ratio // required for proposal to pass), and quorum (votes tallied at this percentage). func (k Keeper) TallyTokenCommitteeVotes(ctx sdk.Context, proposalID uint64, diff --git a/x/committee/types/committee.go b/x/committee/types/committee.go index 86574e88..aa32f6a8 100644 --- a/x/committee/types/committee.go +++ b/x/committee/types/committee.go @@ -381,7 +381,7 @@ func MustNewProposal(pubProposal PubProposal, id uint64, committeeID uint64, dea return proposal } -// GetPubProposal returns the PubProposal (govtypes.Content) +// GetContent returns the PubProposal (govtypes.Content) func (p Proposal) GetContent() PubProposal { content, ok := p.Content.GetCachedValue().(PubProposal) if !ok { diff --git a/x/committee/types/genesis.go b/x/committee/types/genesis.go index e34331b3..11d4bdc4 100644 --- a/x/committee/types/genesis.go +++ b/x/committee/types/genesis.go @@ -7,7 +7,7 @@ import ( proto "github.com/cosmos/gogoproto/proto" ) -// DefaultNextProposalID is the starting poiint for proposal IDs. +// DefaultNextProposalID is the starting point for proposal IDs. const DefaultNextProposalID uint64 = 1 // NewGenesisState returns a new genesis state object for the module. diff --git a/x/evmutil/keeper/bank_keeper.go b/x/evmutil/keeper/bank_keeper.go deleted file mode 100644 index c21fd83b..00000000 --- a/x/evmutil/keeper/bank_keeper.go +++ /dev/null @@ -1,282 +0,0 @@ -package keeper - -import ( - "fmt" - - errorsmod "cosmossdk.io/errors" - sdkmath "cosmossdk.io/math" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - evmtypes "github.com/evmos/ethermint/x/evm/types" - - "github.com/0glabs/0g-chain/chaincfg" - "github.com/0glabs/0g-chain/x/evmutil/types" -) - -// ConversionMultiplier is the conversion multiplier between evm denom and gas denom -var ConversionMultiplier = sdkmath.NewInt(chaincfg.GasDenomConversionMultiplier) - -var _ evmtypes.BankKeeper = EvmBankKeeper{} - -// EvmBankKeeper is a BankKeeper wrapper for the x/evm module to allow the use -// of the 18 decimal evm denom coin on the evm. -// x/evm consumes gas and send coins by minting and burning evm denom coins in its module -// account and then sending the funds to the target account. -// This keeper uses both the gas denom coin and a separate evm denom balance to manage the -// extra percision needed by the evm. -type EvmBankKeeper struct { - evmDenomKeeper Keeper - bk types.BankKeeper - ak types.AccountKeeper -} - -func NewEvmBankKeeper(baseKeeper Keeper, bk types.BankKeeper, ak types.AccountKeeper) EvmBankKeeper { - return EvmBankKeeper{ - evmDenomKeeper: baseKeeper, - bk: bk, - ak: ak, - } -} - -// GetBalance returns the total **spendable** balance of evm denom for a given account by address. -func (k EvmBankKeeper) GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin { - if denom != chaincfg.EvmDenom { - panic(fmt.Errorf("only evm denom %s is supported by EvmBankKeeper", chaincfg.EvmDenom)) - } - - spendableCoins := k.bk.SpendableCoins(ctx, addr) - gasDenomFromBank := spendableCoins.AmountOf(chaincfg.GasDenom) - evmDenomFromBank := spendableCoins.AmountOf(chaincfg.EvmDenom) - evmDenomFromEvmBank := k.evmDenomKeeper.GetBalance(ctx, addr) - - var total sdkmath.Int - - if gasDenomFromBank.IsPositive() { - total = gasDenomFromBank.Mul(ConversionMultiplier).Add(evmDenomFromBank).Add(evmDenomFromEvmBank) - } else { - total = evmDenomFromBank.Add(evmDenomFromEvmBank) - } - return sdk.NewCoin(chaincfg.EvmDenom, total) -} - -// SendCoins transfers evm denom coins from a AccAddress to an AccAddress. -func (k EvmBankKeeper) SendCoins(ctx sdk.Context, senderAddr sdk.AccAddress, recipientAddr sdk.AccAddress, amt sdk.Coins) error { - // SendCoins method is not used by the evm module, but is required by the - // evmtypes.BankKeeper interface. This must be updated if the evm module - // is updated to use SendCoins. - panic("not implemented") -} - -// SendCoinsFromModuleToAccount transfers evm denom coins from a ModuleAccount to an AccAddress. -// It will panic if the module account does not exist. An error is returned if the recipient -// address is black-listed or if sending the tokens fails. -func (k EvmBankKeeper) SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error { - gasDenomCoin, baseDemonCnt, err := SplitEvmDenomCoins(amt) - if err != nil { - return err - } - - if gasDenomCoin.Amount.IsPositive() { - if err := k.bk.SendCoinsFromModuleToAccount(ctx, senderModule, recipientAddr, sdk.NewCoins(gasDenomCoin)); err != nil { - return err - } - } - - senderAddr := k.GetModuleAddress(senderModule) - if err := k.ConvertOneGasDenomToEvmDenomIfNeeded(ctx, senderAddr, baseDemonCnt); err != nil { - return err - } - - if err := k.evmDenomKeeper.SendBalance(ctx, senderAddr, recipientAddr, baseDemonCnt); err != nil { - return err - } - - return k.ConvertEvmDenomToGasDenom(ctx, recipientAddr) -} - -// SendCoinsFromAccountToModule transfers evm denom coins from an AccAddress to a ModuleAccount. -// It will panic if the module account does not exist. -func (k EvmBankKeeper) SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error { - gasDenomCoin, evmDenomCnt, err := SplitEvmDenomCoins(amt) - if err != nil { - return err - } - - if gasDenomCoin.IsPositive() { - if err := k.bk.SendCoinsFromAccountToModule(ctx, senderAddr, recipientModule, sdk.NewCoins(gasDenomCoin)); err != nil { - return err - } - } - - if err := k.ConvertOneGasDenomToEvmDenomIfNeeded(ctx, senderAddr, evmDenomCnt); err != nil { - return err - } - - recipientAddr := k.GetModuleAddress(recipientModule) - if err := k.evmDenomKeeper.SendBalance(ctx, senderAddr, recipientAddr, evmDenomCnt); err != nil { - return err - } - - return k.ConvertEvmDenomToGasDenom(ctx, recipientAddr) -} - -// MintCoins mints evm denom coins by minting the equivalent gas denom coins and any remaining evm denom coins. -// It will panic if the module account does not exist or is unauthorized. -func (k EvmBankKeeper) MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error { - gasDenomCoin, baseDemonCnt, err := SplitEvmDenomCoins(amt) - if err != nil { - return err - } - - if gasDenomCoin.IsPositive() { - if err := k.bk.MintCoins(ctx, moduleName, sdk.NewCoins(gasDenomCoin)); err != nil { - return err - } - } - - recipientAddr := k.GetModuleAddress(moduleName) - if err := k.evmDenomKeeper.AddBalance(ctx, recipientAddr, baseDemonCnt); err != nil { - return err - } - - return k.ConvertEvmDenomToGasDenom(ctx, recipientAddr) -} - -// BurnCoins burns evm denom coins by burning the equivalent gas denom coins and any remaining evm denom coins. -// It will panic if the module account does not exist or is unauthorized. -func (k EvmBankKeeper) BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error { - gasDenomCoin, baseDemonCnt, err := SplitEvmDenomCoins(amt) - if err != nil { - return err - } - - if gasDenomCoin.IsPositive() { - if err := k.bk.BurnCoins(ctx, moduleName, sdk.NewCoins(gasDenomCoin)); err != nil { - return err - } - } - - moduleAddr := k.GetModuleAddress(moduleName) - if err := k.ConvertOneGasDenomToEvmDenomIfNeeded(ctx, moduleAddr, baseDemonCnt); err != nil { - return err - } - - return k.evmDenomKeeper.RemoveBalance(ctx, moduleAddr, baseDemonCnt) -} - -// IsSendEnabledCoins checks the coins provided and returns an ErrSendDisabled -// if any of the coins are not configured for sending. Returns nil if sending is -// enabled for all provided coins. -func (k EvmBankKeeper) IsSendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error { - // IsSendEnabledCoins method is not used by the evm module, but is required by the - // evmtypes.BankKeeper interface. This must be updated if the evm module - // is updated to use IsSendEnabledCoins. - panic("not implemented") -} - -// ConvertOnegasDenomToEvmDenomIfNeeded converts 1 gas denom to evm denom for an address if -// its evm denom balance is smaller than the evmDenomCnt amount. -func (k EvmBankKeeper) ConvertOneGasDenomToEvmDenomIfNeeded(ctx sdk.Context, addr sdk.AccAddress, evmDenomCnt sdkmath.Int) error { - evmDenomBal := k.evmDenomKeeper.GetBalance(ctx, addr) - if evmDenomBal.GTE(evmDenomCnt) { - return nil - } - - gasDenomToStore := sdk.NewCoins(sdk.NewCoin(chaincfg.GasDenom, sdk.OneInt())) - if err := k.bk.SendCoinsFromAccountToModule(ctx, addr, types.ModuleName, gasDenomToStore); err != nil { - return err - } - - // add 1 gas denom equivalent of evm denom to addr - evmDenomToReceive := ConversionMultiplier - if err := k.evmDenomKeeper.AddBalance(ctx, addr, evmDenomToReceive); err != nil { - return err - } - - return nil -} - -// ConvertEvmDenomTogasDenom converts all available evm denom to gas denom for a given AccAddress. -func (k EvmBankKeeper) ConvertEvmDenomToGasDenom(ctx sdk.Context, addr sdk.AccAddress) error { - totalEvmDenom := k.evmDenomKeeper.GetBalance(ctx, addr) - gasDenomCoin, _, err := SplitEvmDenomCoins(sdk.NewCoins(sdk.NewCoin(chaincfg.EvmDenom, totalEvmDenom))) - if err != nil { - return err - } - - // do nothing if account does not have enough evm denom for a single gas denom - gasDenomToReceive := gasDenomCoin.Amount - if !gasDenomToReceive.IsPositive() { - return nil - } - - // remove evm denom used for converting to gas denom - evmDenomToBurn := gasDenomToReceive.Mul(ConversionMultiplier) - finalBal := totalEvmDenom.Sub(evmDenomToBurn) - if err := k.evmDenomKeeper.SetBalance(ctx, addr, finalBal); err != nil { - return err - } - - fromAddr := k.GetModuleAddress(types.ModuleName) - if err := k.bk.SendCoins(ctx, fromAddr, addr, sdk.NewCoins(gasDenomCoin)); err != nil { - return err - } - - return nil -} - -func (k EvmBankKeeper) GetModuleAddress(moduleName string) sdk.AccAddress { - addr := k.ak.GetModuleAddress(moduleName) - if addr == nil { - panic(errorsmod.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", moduleName)) - } - return addr -} - -// SplitEvmDenomCoins splits evm denom coins to the equivalent gas denom coins and any remaining evm denom balance. -// An error will be returned if the coins are not valid or if the coins are not the evm denom. -func SplitEvmDenomCoins(coins sdk.Coins) (sdk.Coin, sdkmath.Int, error) { - baseDemonCnt := sdk.ZeroInt() - gasDenomAmt := sdk.NewCoin(chaincfg.GasDenom, sdk.ZeroInt()) - - if len(coins) == 0 { - return gasDenomAmt, baseDemonCnt, nil - } - - if err := ValidateEvmCoins(coins); err != nil { - return gasDenomAmt, baseDemonCnt, err - } - - // note: we should always have len(coins) == 1 here since coins cannot have dup denoms after we validate. - coin := coins[0] - remainingBalance := coin.Amount.Mod(ConversionMultiplier) - if remainingBalance.IsPositive() { - baseDemonCnt = remainingBalance - } - gasDenomAmount := coin.Amount.Quo(ConversionMultiplier) - if gasDenomAmount.IsPositive() { - gasDenomAmt = sdk.NewCoin(chaincfg.GasDenom, gasDenomAmount) - } - - return gasDenomAmt, baseDemonCnt, nil -} - -// ValidateEvmCoins validates the coins from evm is valid and is the evm denom. -func ValidateEvmCoins(coins sdk.Coins) error { - if len(coins) == 0 { - return nil - } - - // validate that coins are non-negative, sorted, and no dup denoms - if err := coins.Validate(); err != nil { - return errorsmod.Wrap(sdkerrors.ErrInvalidCoins, coins.String()) - } - - // validate that coin denom is evm denom - if len(coins) != 1 || coins[0].Denom != chaincfg.EvmDenom { - errMsg := fmt.Sprintf("invalid evm coin denom, only %s is supported", chaincfg.EvmDenom) - return errorsmod.Wrap(sdkerrors.ErrInvalidCoins, errMsg) - } - - return nil -} diff --git a/x/evmutil/keeper/bank_keeper_test.go b/x/evmutil/keeper/bank_keeper_test.go deleted file mode 100644 index 9fae9f68..00000000 --- a/x/evmutil/keeper/bank_keeper_test.go +++ /dev/null @@ -1,805 +0,0 @@ -package keeper_test - -import ( - "math/big" - "testing" - "time" - - sdkmath "cosmossdk.io/math" - tmtime "github.com/cometbft/cometbft/types/time" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/stretchr/testify/suite" - - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - vesting "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" - evmtypes "github.com/evmos/ethermint/x/evm/types" - - "github.com/0glabs/0g-chain/chaincfg" - "github.com/0glabs/0g-chain/x/evmutil/keeper" - "github.com/0glabs/0g-chain/x/evmutil/testutil" - "github.com/0glabs/0g-chain/x/evmutil/types" -) - -type evmBankKeeperTestSuite struct { - testutil.Suite -} - -func (suite *evmBankKeeperTestSuite) SetupTest() { - suite.Suite.SetupTest() -} - -func (suite *evmBankKeeperTestSuite) TestGetBalance_ReturnsSpendable() { - startingCoins := sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 10)) - startingEvmDenom := sdkmath.NewInt(100) - - now := tmtime.Now() - endTime := now.Add(24 * time.Hour) - bacc := authtypes.NewBaseAccountWithAddress(suite.Addrs[0]) - vacc := vesting.NewContinuousVestingAccount(bacc, startingCoins, now.Unix(), endTime.Unix()) - suite.AccountKeeper.SetAccount(suite.Ctx, vacc) - - err := suite.App.FundAccount(suite.Ctx, suite.Addrs[0], startingCoins) - suite.Require().NoError(err) - err = suite.Keeper.SetBalance(suite.Ctx, suite.Addrs[0], startingEvmDenom) - suite.Require().NoError(err) - - coin := suite.EvmBankKeeper.GetBalance(suite.Ctx, suite.Addrs[0], chaincfg.EvmDenom) - suite.Require().Equal(startingEvmDenom, coin.Amount) - - ctx := suite.Ctx.WithBlockTime(now.Add(12 * time.Hour)) - coin = suite.EvmBankKeeper.GetBalance(ctx, suite.Addrs[0], chaincfg.EvmDenom) - suite.Require().Equal(sdkmath.NewIntFromUint64(5_000_000_000_100), coin.Amount) -} - -func (suite *evmBankKeeperTestSuite) TestGetBalance_NotEvmDenom() { - suite.Require().Panics(func() { - suite.EvmBankKeeper.GetBalance(suite.Ctx, suite.Addrs[0], chaincfg.GasDenom) - }) - suite.Require().Panics(func() { - suite.EvmBankKeeper.GetBalance(suite.Ctx, suite.Addrs[0], "busd") - }) -} - -func (suite *evmBankKeeperTestSuite) TestGetBalance() { - tests := []struct { - name string - startingAmount sdk.Coins - expAmount sdkmath.Int - }{ - { - "gas denom with evm denom", - sdk.NewCoins( - sdk.NewInt64Coin(chaincfg.EvmDenom, 100), - sdk.NewInt64Coin(chaincfg.GasDenom, 10), - ), - sdkmath.NewInt(10_000_000_000_100), - }, - { - "just evm denom", - sdk.NewCoins( - sdk.NewInt64Coin(chaincfg.EvmDenom, 100), - sdk.NewInt64Coin("busd", 100), - ), - sdkmath.NewInt(100), - }, - { - "just gas denom", - sdk.NewCoins( - sdk.NewInt64Coin(chaincfg.GasDenom, 10), - sdk.NewInt64Coin("busd", 100), - ), - sdkmath.NewInt(10_000_000_000_000), - }, - { - "no gas denom or evm denom", - sdk.NewCoins(), - sdk.ZeroInt(), - }, - { - "with avaka that is more than 1 gas denom", - sdk.NewCoins( - sdk.NewInt64Coin(chaincfg.EvmDenom, 20_000_000_000_220), - sdk.NewInt64Coin(chaincfg.GasDenom, 11), - ), - sdkmath.NewInt(31_000_000_000_220), - }, - } - - for _, tt := range tests { - suite.Run(tt.name, func() { - suite.SetupTest() - - suite.FundAccountWithZgChain(suite.Addrs[0], tt.startingAmount) - coin := suite.EvmBankKeeper.GetBalance(suite.Ctx, suite.Addrs[0], chaincfg.EvmDenom) - suite.Require().Equal(tt.expAmount, coin.Amount) - }) - } -} - -func (suite *evmBankKeeperTestSuite) TestSendCoinsFromModuleToAccount() { - startingModuleCoins := sdk.NewCoins( - sdk.NewInt64Coin(chaincfg.EvmDenom, 200), - sdk.NewInt64Coin(chaincfg.GasDenom, 100), - ) - tests := []struct { - name string - sendCoins sdk.Coins - startingAccBal sdk.Coins - expAccBal sdk.Coins - hasErr bool - }{ - { - "send more than 1 gas denom", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 12_000_000_000_010)), - sdk.Coins{}, - sdk.NewCoins( - sdk.NewInt64Coin(chaincfg.EvmDenom, 10), - sdk.NewInt64Coin(chaincfg.GasDenom, 12), - ), - false, - }, - { - "send less than 1 gas denom", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 122)), - sdk.Coins{}, - sdk.NewCoins( - sdk.NewInt64Coin(chaincfg.EvmDenom, 122), - sdk.NewInt64Coin(chaincfg.GasDenom, 0), - ), - false, - }, - { - "send an exact amount of gas denom", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 98_000_000_000_000)), - sdk.Coins{}, - sdk.NewCoins( - sdk.NewInt64Coin(chaincfg.EvmDenom, 0o0), - sdk.NewInt64Coin(chaincfg.GasDenom, 98), - ), - false, - }, - { - "send no evm denom", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 0)), - sdk.Coins{}, - sdk.NewCoins( - sdk.NewInt64Coin(chaincfg.EvmDenom, 0), - sdk.NewInt64Coin(chaincfg.GasDenom, 0), - ), - false, - }, - { - "errors if sending other coins", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 500), sdk.NewInt64Coin("busd", 1000)), - sdk.Coins{}, - sdk.Coins{}, - true, - }, - { - "errors if not enough total evm denom to cover", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 100_000_000_001_000)), - sdk.Coins{}, - sdk.Coins{}, - true, - }, - { - "errors if not enough gas denom to cover", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 200_000_000_000_000)), - sdk.Coins{}, - sdk.Coins{}, - true, - }, - { - "converts receiver's evm denom to gas denom if there's enough evm denom after the transfer", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 99_000_000_000_200)), - sdk.NewCoins( - sdk.NewInt64Coin(chaincfg.EvmDenom, 999_999_999_900), - sdk.NewInt64Coin(chaincfg.GasDenom, 1), - ), - sdk.NewCoins( - sdk.NewInt64Coin(chaincfg.EvmDenom, 100), - sdk.NewInt64Coin(chaincfg.GasDenom, 101), - ), - false, - }, - { - "converts all of receiver's evm denom to gas denom even if somehow receiver has more than 1 gas denom of evm denom", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 12_000_000_000_100)), - sdk.NewCoins( - sdk.NewInt64Coin(chaincfg.EvmDenom, 5_999_999_999_990), - sdk.NewInt64Coin(chaincfg.GasDenom, 1), - ), - sdk.NewCoins( - sdk.NewInt64Coin(chaincfg.EvmDenom, 90), - sdk.NewInt64Coin(chaincfg.GasDenom, 19), - ), - false, - }, - { - "swap 1 gas denom for evm denom if module account doesn't have enough evm denom", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 99_000_000_001_000)), - sdk.NewCoins( - sdk.NewInt64Coin(chaincfg.EvmDenom, 200), - sdk.NewInt64Coin(chaincfg.GasDenom, 1), - ), - sdk.NewCoins( - sdk.NewInt64Coin(chaincfg.EvmDenom, 1200), - sdk.NewInt64Coin(chaincfg.GasDenom, 100), - ), - false, - }, - } - - for _, tt := range tests { - suite.Run(tt.name, func() { - suite.SetupTest() - - suite.FundAccountWithZgChain(suite.Addrs[0], tt.startingAccBal) - suite.FundModuleAccountWithZgChain(evmtypes.ModuleName, startingModuleCoins) - - // fund our module with some gas denom to account for converting extra evm denom back to gas denom - suite.FundModuleAccountWithZgChain(types.ModuleName, sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 10))) - - err := suite.EvmBankKeeper.SendCoinsFromModuleToAccount(suite.Ctx, evmtypes.ModuleName, suite.Addrs[0], tt.sendCoins) - if tt.hasErr { - suite.Require().Error(err) - return - } else { - suite.Require().NoError(err) - } - - // check gas denom - GasDenomSender := suite.BankKeeper.GetBalance(suite.Ctx, suite.Addrs[0], chaincfg.GasDenom) - suite.Require().Equal(tt.expAccBal.AmountOf(chaincfg.GasDenom).Int64(), GasDenomSender.Amount.Int64()) - - // check evm denom - actualEvmDenom := suite.Keeper.GetBalance(suite.Ctx, suite.Addrs[0]) - suite.Require().Equal(tt.expAccBal.AmountOf(chaincfg.EvmDenom).Int64(), actualEvmDenom.Int64()) - }) - } -} - -func (suite *evmBankKeeperTestSuite) TestSendCoinsFromAccountToModule() { - startingAccCoins := sdk.NewCoins( - sdk.NewInt64Coin(chaincfg.EvmDenom, 200), - sdk.NewInt64Coin(chaincfg.GasDenom, 100), - ) - startingModuleCoins := sdk.NewCoins( - sdk.NewInt64Coin(chaincfg.EvmDenom, 100_000_000_000), - ) - tests := []struct { - name string - sendCoins sdk.Coins - expSenderCoins sdk.Coins - expModuleCoins sdk.Coins - hasErr bool - }{ - { - "send more than 1 gas denom", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 12_000_000_000_010)), - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 190), sdk.NewInt64Coin(chaincfg.GasDenom, 88)), - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 100_000_000_010), sdk.NewInt64Coin(chaincfg.GasDenom, 12)), - false, - }, - { - "send less than 1 gas denom", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 122)), - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 78), sdk.NewInt64Coin(chaincfg.GasDenom, 100)), - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 100_000_000_122), sdk.NewInt64Coin(chaincfg.GasDenom, 0)), - false, - }, - { - "send an exact amount of gas denom", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 98_000_000_000_000)), - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 200), sdk.NewInt64Coin(chaincfg.GasDenom, 2)), - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 100_000_000_000), sdk.NewInt64Coin(chaincfg.GasDenom, 98)), - false, - }, - { - "send no evm denom", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 0)), - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 200), sdk.NewInt64Coin(chaincfg.GasDenom, 100)), - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 100_000_000_000), sdk.NewInt64Coin(chaincfg.GasDenom, 0)), - false, - }, - { - "errors if sending other coins", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 500), sdk.NewInt64Coin("busd", 1000)), - sdk.Coins{}, - sdk.Coins{}, - true, - }, - { - "errors if have dup coins", - sdk.Coins{ - sdk.NewInt64Coin(chaincfg.EvmDenom, 12_000_000_000_000), - sdk.NewInt64Coin(chaincfg.EvmDenom, 2_000_000_000_000), - }, - sdk.Coins{}, - sdk.Coins{}, - true, - }, - { - "errors if not enough total evm denom to cover", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 100_000_000_001_000)), - sdk.Coins{}, - sdk.Coins{}, - true, - }, - { - "errors if not enough gas denom to cover", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 200_000_000_000_000)), - sdk.Coins{}, - sdk.Coins{}, - true, - }, - { - "converts 1 gas denom to evm denom if not enough evm denom to cover", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 99_001_000_000_000)), - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 999_000_000_200), sdk.NewInt64Coin(chaincfg.GasDenom, 0)), - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 101_000_000_000), sdk.NewInt64Coin(chaincfg.GasDenom, 99)), - false, - }, - { - "converts receiver's evm denom to gas denom if there's enough evm denom after the transfer", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 5_900_000_000_200)), - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 100_000_000_000), sdk.NewInt64Coin(chaincfg.GasDenom, 94)), - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 200), sdk.NewInt64Coin(chaincfg.GasDenom, 6)), - false, - }, - } - - for _, tt := range tests { - suite.Run(tt.name, func() { - suite.SetupTest() - suite.FundAccountWithZgChain(suite.Addrs[0], startingAccCoins) - suite.FundModuleAccountWithZgChain(evmtypes.ModuleName, startingModuleCoins) - - err := suite.EvmBankKeeper.SendCoinsFromAccountToModule(suite.Ctx, suite.Addrs[0], evmtypes.ModuleName, tt.sendCoins) - if tt.hasErr { - suite.Require().Error(err) - return - } else { - suite.Require().NoError(err) - } - - // check sender balance - GasDenomSender := suite.BankKeeper.GetBalance(suite.Ctx, suite.Addrs[0], chaincfg.GasDenom) - suite.Require().Equal(tt.expSenderCoins.AmountOf(chaincfg.GasDenom).Int64(), GasDenomSender.Amount.Int64()) - actualEvmDenom := suite.Keeper.GetBalance(suite.Ctx, suite.Addrs[0]) - suite.Require().Equal(tt.expSenderCoins.AmountOf(chaincfg.EvmDenom).Int64(), actualEvmDenom.Int64()) - - // check module balance - moduleAddr := suite.AccountKeeper.GetModuleAddress(evmtypes.ModuleName) - GasDenomSender = suite.BankKeeper.GetBalance(suite.Ctx, moduleAddr, chaincfg.GasDenom) - suite.Require().Equal(tt.expModuleCoins.AmountOf(chaincfg.GasDenom).Int64(), GasDenomSender.Amount.Int64()) - actualEvmDenom = suite.Keeper.GetBalance(suite.Ctx, moduleAddr) - suite.Require().Equal(tt.expModuleCoins.AmountOf(chaincfg.EvmDenom).Int64(), actualEvmDenom.Int64()) - }) - } -} - -func (suite *evmBankKeeperTestSuite) TestBurnCoins() { - startingGasDenom := sdkmath.NewInt(100) - tests := []struct { - name string - burnCoins sdk.Coins - expGasDenom sdkmath.Int - expEvmDenom sdkmath.Int - hasErr bool - evmDenomStart sdkmath.Int - }{ - { - "burn more than 1 gas denom", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 12_021_000_000_002)), - sdkmath.NewInt(88), - sdkmath.NewInt(100_000_000_000), - false, - sdkmath.NewInt(121_000_000_002), - }, - { - "burn less than 1 gas denom", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 122)), - sdkmath.NewInt(100), - sdkmath.NewInt(878), - false, - sdkmath.NewInt(1000), - }, - { - "burn an exact amount of gas denom", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 98_000_000_000_000)), - sdkmath.NewInt(2), - sdkmath.NewInt(10), - false, - sdkmath.NewInt(10), - }, - { - "burn no evm denom", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 0)), - startingGasDenom, - sdk.ZeroInt(), - false, - sdk.ZeroInt(), - }, - { - "errors if burning other coins", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 500), sdk.NewInt64Coin("busd", 1000)), - startingGasDenom, - sdkmath.NewInt(100), - true, - sdkmath.NewInt(100), - }, - { - "errors if have dup coins", - sdk.Coins{ - sdk.NewInt64Coin(chaincfg.EvmDenom, 12_000_000_000_000), - sdk.NewInt64Coin(chaincfg.EvmDenom, 2_000_000_000_000), - }, - startingGasDenom, - sdk.ZeroInt(), - true, - sdk.ZeroInt(), - }, - { - "errors if burn amount is negative", - sdk.Coins{sdk.Coin{Denom: chaincfg.EvmDenom, Amount: sdkmath.NewInt(-100)}}, - startingGasDenom, - sdkmath.NewInt(50), - true, - sdkmath.NewInt(50), - }, - { - "errors if not enough evm denom to cover burn", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 100_999_000_000_000)), - sdkmath.NewInt(0), - sdkmath.NewInt(99_000_000_000), - true, - sdkmath.NewInt(99_000_000_000), - }, - { - "errors if not enough gas denom to cover burn", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 200_000_000_000_000)), - sdkmath.NewInt(100), - sdk.ZeroInt(), - true, - sdk.ZeroInt(), - }, - { - "converts 1 gas denom to evm denom if not enough evm denom to cover", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 12_021_000_000_002)), - sdkmath.NewInt(87), - sdkmath.NewInt(980_000_000_000), - false, - sdkmath.NewInt(1_000_000_002), - }, - } - - for _, tt := range tests { - suite.Run(tt.name, func() { - suite.SetupTest() - startingCoins := sdk.NewCoins( - sdk.NewCoin(chaincfg.GasDenom, startingGasDenom), - sdk.NewCoin(chaincfg.EvmDenom, tt.evmDenomStart), - ) - suite.FundModuleAccountWithZgChain(evmtypes.ModuleName, startingCoins) - - err := suite.EvmBankKeeper.BurnCoins(suite.Ctx, evmtypes.ModuleName, tt.burnCoins) - if tt.hasErr { - suite.Require().Error(err) - return - } else { - suite.Require().NoError(err) - } - - // check gas denom - GasDenomActual := suite.BankKeeper.GetBalance(suite.Ctx, suite.EvmModuleAddr, chaincfg.GasDenom) - suite.Require().Equal(tt.expGasDenom, GasDenomActual.Amount) - - // check evm denom - evmDenomActual := suite.Keeper.GetBalance(suite.Ctx, suite.EvmModuleAddr) - suite.Require().Equal(tt.expEvmDenom, evmDenomActual) - }) - } -} - -func (suite *evmBankKeeperTestSuite) TestMintCoins() { - tests := []struct { - name string - mintCoins sdk.Coins - GasDenomCnt sdkmath.Int - evmDenomCnt sdkmath.Int - hasErr bool - evmDenomStart sdkmath.Int - }{ - { - "mint more than 1 gas denom", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 12_021_000_000_002)), - sdkmath.NewInt(12), - sdkmath.NewInt(21_000_000_002), - false, - sdk.ZeroInt(), - }, - { - "mint less than 1 gas denom", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 901_000_000_001)), - sdk.ZeroInt(), - sdkmath.NewInt(901_000_000_001), - false, - sdk.ZeroInt(), - }, - { - "mint an exact amount of gas denom", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 123_000_000_000_000_000)), - sdkmath.NewInt(123_000), - sdk.ZeroInt(), - false, - sdk.ZeroInt(), - }, - { - "mint no evm denom", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 0)), - sdk.ZeroInt(), - sdk.ZeroInt(), - false, - sdk.ZeroInt(), - }, - { - "errors if minting other coins", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 500), sdk.NewInt64Coin("busd", 1000)), - sdk.ZeroInt(), - sdkmath.NewInt(100), - true, - sdkmath.NewInt(100), - }, - { - "errors if have dup coins", - sdk.Coins{ - sdk.NewInt64Coin(chaincfg.EvmDenom, 12_000_000_000_000), - sdk.NewInt64Coin(chaincfg.EvmDenom, 2_000_000_000_000), - }, - sdk.ZeroInt(), - sdk.ZeroInt(), - true, - sdk.ZeroInt(), - }, - { - "errors if mint amount is negative", - sdk.Coins{sdk.Coin{Denom: chaincfg.EvmDenom, Amount: sdkmath.NewInt(-100)}}, - sdk.ZeroInt(), - sdkmath.NewInt(50), - true, - sdkmath.NewInt(50), - }, - { - "adds to existing evm denom balance", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 12_021_000_000_002)), - sdkmath.NewInt(12), - sdkmath.NewInt(21_000_000_102), - false, - sdkmath.NewInt(100), - }, - { - "convert evm denom balance to gas denom if it exceeds 1 gas denom", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 10_999_000_000_000)), - sdkmath.NewInt(12), - sdkmath.NewInt(1_200_000_001), - false, - sdkmath.NewInt(1_002_200_000_001), - }, - } - - for _, tt := range tests { - suite.Run(tt.name, func() { - suite.SetupTest() - suite.FundModuleAccountWithZgChain(types.ModuleName, sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 10))) - suite.FundModuleAccountWithZgChain(evmtypes.ModuleName, sdk.NewCoins(sdk.NewCoin(chaincfg.EvmDenom, tt.evmDenomStart))) - - err := suite.EvmBankKeeper.MintCoins(suite.Ctx, evmtypes.ModuleName, tt.mintCoins) - if tt.hasErr { - suite.Require().Error(err) - return - } else { - suite.Require().NoError(err) - } - - // check gas denom - GasDenomActual := suite.BankKeeper.GetBalance(suite.Ctx, suite.EvmModuleAddr, chaincfg.GasDenom) - suite.Require().Equal(tt.GasDenomCnt, GasDenomActual.Amount) - - // check evm denom - evmDenomActual := suite.Keeper.GetBalance(suite.Ctx, suite.EvmModuleAddr) - suite.Require().Equal(tt.evmDenomCnt, evmDenomActual) - }) - } -} - -func (suite *evmBankKeeperTestSuite) TestValidateEvmCoins() { - tests := []struct { - name string - coins sdk.Coins - shouldErr bool - }{ - { - "valid coins", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 500)), - false, - }, - { - "dup coins", - sdk.Coins{sdk.NewInt64Coin(chaincfg.EvmDenom, 500), sdk.NewInt64Coin(chaincfg.EvmDenom, 500)}, - true, - }, - { - "not evm coins", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 500)), - true, - }, - { - "negative coins", - sdk.Coins{sdk.Coin{Denom: chaincfg.EvmDenom, Amount: sdkmath.NewInt(-500)}}, - true, - }, - } - for _, tt := range tests { - suite.Run(tt.name, func() { - err := keeper.ValidateEvmCoins(tt.coins) - if tt.shouldErr { - suite.Require().Error(err) - } else { - suite.Require().NoError(err) - } - }) - } -} - -func (suite *evmBankKeeperTestSuite) TestConvertOneGasDenomToEvmDenomIfNeeded() { - evmDenomNeeded := sdkmath.NewInt(200) - tests := []struct { - name string - startingCoins sdk.Coins - expectedCoins sdk.Coins - success bool - }{ - { - "not enough gas denom for conversion", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 100)), - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 100)), - false, - }, - { - "converts 1 gas denom to evm denom", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 10), sdk.NewInt64Coin(chaincfg.EvmDenom, 100)), - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 9), sdk.NewInt64Coin(chaincfg.EvmDenom, 1_000_000_000_100)), - true, - }, - { - "conversion not needed", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 10), sdk.NewInt64Coin(chaincfg.EvmDenom, 200)), - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 10), sdk.NewInt64Coin(chaincfg.EvmDenom, 200)), - true, - }, - } - for _, tt := range tests { - suite.Run(tt.name, func() { - suite.SetupTest() - - suite.FundAccountWithZgChain(suite.Addrs[0], tt.startingCoins) - err := suite.EvmBankKeeper.ConvertOneGasDenomToEvmDenomIfNeeded(suite.Ctx, suite.Addrs[0], evmDenomNeeded) - moduleZgChain := suite.BankKeeper.GetBalance(suite.Ctx, suite.AccountKeeper.GetModuleAddress(types.ModuleName), chaincfg.GasDenom) - if tt.success { - suite.Require().NoError(err) - if tt.startingCoins.AmountOf(chaincfg.EvmDenom).LT(evmDenomNeeded) { - suite.Require().Equal(sdk.OneInt(), moduleZgChain.Amount) - } - } else { - suite.Require().Error(err) - suite.Require().Equal(sdk.ZeroInt(), moduleZgChain.Amount) - } - - evmDenomCnt := suite.Keeper.GetBalance(suite.Ctx, suite.Addrs[0]) - suite.Require().Equal(tt.expectedCoins.AmountOf(chaincfg.EvmDenom), evmDenomCnt) - GasDenomCoin := suite.BankKeeper.GetBalance(suite.Ctx, suite.Addrs[0], chaincfg.GasDenom) - suite.Require().Equal(tt.expectedCoins.AmountOf(chaincfg.GasDenom), GasDenomCoin.Amount) - }) - } -} - -func (suite *evmBankKeeperTestSuite) TestConvertEvmDenomToGasDenom() { - tests := []struct { - name string - startingCoins sdk.Coins - expectedCoins sdk.Coins - }{ - { - "not enough gas denom", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 100)), - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 100), sdk.NewInt64Coin(chaincfg.GasDenom, 0)), - }, - { - "converts evm denom for 1 gas denom", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 10), sdk.NewInt64Coin(chaincfg.EvmDenom, 1_000_000_000_003)), - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 11), sdk.NewInt64Coin(chaincfg.EvmDenom, 3)), - }, - { - "converts more than 1 gas denom of evm denom", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 10), sdk.NewInt64Coin(chaincfg.EvmDenom, 8_000_000_000_123)), - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 18), sdk.NewInt64Coin(chaincfg.EvmDenom, 123)), - }, - } - for _, tt := range tests { - suite.Run(tt.name, func() { - suite.SetupTest() - - err := suite.App.FundModuleAccount(suite.Ctx, types.ModuleName, sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 10))) - suite.Require().NoError(err) - suite.FundAccountWithZgChain(suite.Addrs[0], tt.startingCoins) - err = suite.EvmBankKeeper.ConvertEvmDenomToGasDenom(suite.Ctx, suite.Addrs[0]) - suite.Require().NoError(err) - evmDenomCnt := suite.Keeper.GetBalance(suite.Ctx, suite.Addrs[0]) - suite.Require().Equal(tt.expectedCoins.AmountOf(chaincfg.EvmDenom), evmDenomCnt) - GasDenomCoin := suite.BankKeeper.GetBalance(suite.Ctx, suite.Addrs[0], chaincfg.GasDenom) - suite.Require().Equal(tt.expectedCoins.AmountOf(chaincfg.GasDenom), GasDenomCoin.Amount) - }) - } -} - -func (suite *evmBankKeeperTestSuite) TestSplitEvmDenomCoins() { - tests := []struct { - name string - coins sdk.Coins - expectedCoins sdk.Coins - shouldErr bool - }{ - { - "invalid coins", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 500)), - nil, - true, - }, - { - "empty coins", - sdk.NewCoins(), - sdk.NewCoins(), - false, - }, - { - "gas denom & evm denom coins", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 8_000_000_000_123)), - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 8), sdk.NewInt64Coin(chaincfg.EvmDenom, 123)), - false, - }, - { - "only evm denom", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 10_123)), - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 10_123)), - false, - }, - { - "only gas denom", - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.EvmDenom, 5_000_000_000_000)), - sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 5)), - false, - }, - } - for _, tt := range tests { - suite.Run(tt.name, func() { - GasDenomCoin, evmDenomCnt, err := keeper.SplitEvmDenomCoins(tt.coins) - if tt.shouldErr { - suite.Require().Error(err) - } else { - suite.Require().NoError(err) - suite.Require().Equal(tt.expectedCoins.AmountOf(chaincfg.GasDenom), GasDenomCoin.Amount) - suite.Require().Equal(tt.expectedCoins.AmountOf(chaincfg.EvmDenom), evmDenomCnt) - } - }) - } -} - -func TestEvmBankKeeperTestSuite(t *testing.T) { - suite.Run(t, new(evmBankKeeperTestSuite)) -} - -func makeBigIntByString(s string) *big.Int { - i, _ := new(big.Int).SetString(s, 10) - return i -} diff --git a/x/evmutil/keeper/invariants.go b/x/evmutil/keeper/invariants.go index afbfbbf5..26d9a533 100644 --- a/x/evmutil/keeper/invariants.go +++ b/x/evmutil/keeper/invariants.go @@ -6,14 +6,11 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - "github.com/0glabs/0g-chain/chaincfg" "github.com/0glabs/0g-chain/x/evmutil/types" ) // RegisterInvariants registers the swap module invariants func RegisterInvariants(ir sdk.InvariantRegistry, bankK types.BankKeeper, k Keeper) { - ir.RegisterRoute(types.ModuleName, "fully-backed", FullyBackedInvariant(bankK, k)) - ir.RegisterRoute(types.ModuleName, "small-balances", SmallBalancesInvariant(bankK, k)) ir.RegisterRoute(types.ModuleName, "cosmos-coins-fully-backed", CosmosCoinsFullyBackedInvariant(bankK, k)) // Disable this invariant due to some issues with it requiring some staking params to be set in genesis. // ir.RegisterRoute(types.ModuleName, "backed-conversion-coins", BackedCoinsInvariant(bankK, k)) @@ -22,57 +19,11 @@ func RegisterInvariants(ir sdk.InvariantRegistry, bankK types.BankKeeper, k Keep // AllInvariants runs all invariants of the swap module func AllInvariants(bankK types.BankKeeper, k Keeper) sdk.Invariant { return func(ctx sdk.Context) (string, bool) { - if res, stop := FullyBackedInvariant(bankK, k)(ctx); stop { - return res, stop - } if res, stop := BackedCoinsInvariant(bankK, k)(ctx); stop { return res, stop } - if res, stop := CosmosCoinsFullyBackedInvariant(bankK, k)(ctx); stop { - return res, stop - } - return SmallBalancesInvariant(bankK, k)(ctx) - } -} -// FullyBackedInvariant ensures all minor balances are backed by the coins in the module account. -// -// The module balance can be greater than the sum of all minor balances. This can happen in rare cases -// where the evm module burns tokens. -func FullyBackedInvariant(bankK types.BankKeeper, k Keeper) sdk.Invariant { - broken := false - message := sdk.FormatInvariant(types.ModuleName, "fully backed broken", "sum of minor balances greater than module account") - - return func(ctx sdk.Context) (string, bool) { - totalMinorBalances := sdk.ZeroInt() - k.IterateAllAccounts(ctx, func(acc types.Account) bool { - totalMinorBalances = totalMinorBalances.Add(acc.Balance) - return false - }) - - bankAddr := authtypes.NewModuleAddress(types.ModuleName) - bankBalance := bankK.GetBalance(ctx, bankAddr, chaincfg.GasDenom).Amount.Mul(ConversionMultiplier) - - broken = totalMinorBalances.GT(bankBalance) - - return message, broken - } -} - -// SmallBalancesInvariant ensures all minor balances are less than the overflow amount, beyond this they should be converted to the major denom. -func SmallBalancesInvariant(_ types.BankKeeper, k Keeper) sdk.Invariant { - broken := false - message := sdk.FormatInvariant(types.ModuleName, "small balances broken", "minor balances not all less than overflow") - - return func(ctx sdk.Context) (string, bool) { - k.IterateAllAccounts(ctx, func(account types.Account) bool { - if account.Balance.GTE(ConversionMultiplier) { - broken = true - return true - } - return false - }) - return message, broken + return CosmosCoinsFullyBackedInvariant(bankK, k)(ctx) } } diff --git a/x/evmutil/keeper/invariants_test.go b/x/evmutil/keeper/invariants_test.go index 79fc4474..5a741ed4 100644 --- a/x/evmutil/keeper/invariants_test.go +++ b/x/evmutil/keeper/invariants_test.go @@ -44,7 +44,7 @@ func (suite *invariantTestSuite) SetupValidState() { for i := 0; i < 4; i++ { suite.Keeper.SetAccount(suite.Ctx, *types.NewAccount( suite.Addrs[i], - keeper.ConversionMultiplier.QuoRaw(2), + sdkmath.NewInt(10000000000), )) } suite.FundModuleAccountWithZgChain( @@ -97,7 +97,7 @@ func (suite *invariantTestSuite) SetupValidState() { suite.NoError(err) } -// RegisterRoutes implements sdk.InvariantRegistry +// RegisterRoute implements sdk.InvariantRegistry func (suite *invariantTestSuite) RegisterRoute(moduleName string, route string, invariant sdk.Invariant) { _, exists := suite.invariants[moduleName] @@ -132,45 +132,6 @@ func (suite *invariantTestSuite) runInvariant(route string, invariant func(bankK return dMessage, dBroken } -func (suite *invariantTestSuite) TestFullyBackedInvariant() { - // default state is valid - _, broken := suite.runInvariant("fully-backed", keeper.FullyBackedInvariant) - suite.Equal(false, broken) - - suite.SetupValidState() - _, broken = suite.runInvariant("fully-backed", keeper.FullyBackedInvariant) - suite.Equal(false, broken) - - // break invariant by increasing total minor balances above module balance - suite.Keeper.AddBalance(suite.Ctx, suite.Addrs[0], sdk.OneInt()) - - message, broken := suite.runInvariant("fully-backed", keeper.FullyBackedInvariant) - suite.Equal("evmutil: fully backed broken invariant\nsum of minor balances greater than module account\n", message) - suite.Equal(true, broken) -} - -func (suite *invariantTestSuite) TestSmallBalances() { - // default state is valid - _, broken := suite.runInvariant("small-balances", keeper.SmallBalancesInvariant) - suite.Equal(false, broken) - - suite.SetupValidState() - _, broken = suite.runInvariant("small-balances", keeper.SmallBalancesInvariant) - suite.Equal(false, broken) - - // increase minor balance at least above conversion multiplier - suite.Keeper.AddBalance(suite.Ctx, suite.Addrs[0], keeper.ConversionMultiplier) - // add same number of gas denom to avoid breaking other invariants - amt := sdk.NewCoins(sdk.NewInt64Coin(chaincfg.GasDenom, 1)) - suite.Require().NoError( - suite.App.FundModuleAccount(suite.Ctx, types.ModuleName, amt), - ) - - message, broken := suite.runInvariant("small-balances", keeper.SmallBalancesInvariant) - suite.Equal("evmutil: small balances broken invariant\nminor balances not all less than overflow\n", message) - suite.Equal(true, broken) -} - // the cosmos-coins-fully-backed invariant depends on 1-to-1 mapping of module balance to erc20s // if coins can be sent directly to the module account, this assumption is broken. // this test verifies that coins cannot be directly sent to the module account. diff --git a/x/evmutil/spec/01_concepts.md b/x/evmutil/spec/01_concepts.md index 7e3f9c82..1bfaf121 100644 --- a/x/evmutil/spec/01_concepts.md +++ b/x/evmutil/spec/01_concepts.md @@ -4,34 +4,6 @@ order: 1 # Concepts -## EVM Gas Denom - -In order to use the EVM and be compatible with existing clients, the gas denom used by the EVM must be in 18 decimals. Since `ukava` has 6 decimals of precision, it cannot be used as the EVM gas denom directly. - -To use the Kava token on the EVM, the evmutil module provides an `EvmBankKeeper` that is responsible for the conversion of `ukava` and `akava`. A user's excess `akava` balance is stored in the `x/evmutil` store, while its `ukava` balance remains in the cosmos-sdk `x/bank` module. - -## `EvmBankKeeper` Overview - -The `EvmBankKeeper` provides access to an account's total `akava` balance and the ability to transfer, mint, and burn `akava`. If anything other than the `akava` denom is requested, the `EvmBankKeeper` will panic. - -This keeper implements the `x/evm` module's `BankKeeper` interface to enable the usage of `akava` denom on the EVM. - -### `x/evm` Parameter Requirements - -Since the EVM denom `akava` is required to use the `EvmBankKeeper`, it is necessary to set the `EVMDenom` param of the `x/evm` module to `akava`. - -### Balance Calculation of `akava` - -The `akava` balance of an account is derived from an account's **spendable** `ukava` balance times 10^12 (to derive its `akava` equivalent), plus the account's excess `akava` balance that can be accessed via the module `Keeper`. - -### `akava` <> `ukava` Conversion - -When an account does not have sufficient `akava` to cover a transfer or burn, the `EvmBankKeeper` will try to swap 1 `ukava` to its equivalent `akava` amount. It does this by transferring 1 `ukava` from the sender to the `x/evmutil` module account, then adding the equivalent `akava` amount to the sender's balance in the module state. - -In reverse, if an account has enough `akava` balance for one or more `ukava`, the excess `akava` balance will be converted to `ukava`. This is done by removing the excess `akava` balance in the module store, then transferring the equivalent `ukava` coins from the `x/evmutil` module account to the target account. - -The swap logic ensures that all `akava` is backed by the equivalent `ukava` balance stored in the module account. - ## ERC20 token <> sdk.Coin Conversion `x/evmutil` facilitates moving assets between Kava's EVM and Cosmos co-chains. This must be handled differently depending on which co-chain to which the asset it native. The messages controlling these flows involve two accounts: @@ -46,7 +18,7 @@ When converting assets from the Cosmos co-chain to the EVM, the initiator is a ` `sdk.Coin`s native to the Cosmos co-chain can be converted to an ERC-20 representing the coin in the EVM. This works by transferring the coin from the initiator to `x/evmutil`'s module account and then minting an ERC-20 token to the receiver. Converting back, the initiator's ERC-20 representation of the coin is burned and the original Cosmos-native asset is transferred to the receiver. -Cosmos-native asset converstion is done through the use of the `MsgConvertCosmosCoinToERC20` & `MsgConvertCosmosCoinFromERC20` messages (see **[Messages](03_messages.md)**). +Cosmos-native asset conversion is done through the use of the `MsgConvertCosmosCoinToERC20` & `MsgConvertCosmosCoinFromERC20` messages (see **[Messages](03_messages.md)**). Only Cosmos co-chain denominations that are in the `AllowedCosmosDenoms` param (see **[Params](05_params.md)**) can be converted via these messages. @@ -65,7 +37,3 @@ EVM-native asset conversion is done through the use of the `MsgConvertERC20ToCoi Only ERC20 contract address that are in the `EnabledConversionPairs` param (see **[Params](05_params.md)**) can be converted via these messages. `EnabledConversionPairs` can be altered through governance. - -## Module Keeper - -The module Keeper provides access to an account's excess `akava` balance and the ability to update the balance. diff --git a/x/evmutil/spec/02_state.md b/x/evmutil/spec/02_state.md index 9d861d9c..763f4d61 100644 --- a/x/evmutil/spec/02_state.md +++ b/x/evmutil/spec/02_state.md @@ -51,24 +51,12 @@ message AllowedCosmosCoinERC20Token { ```protobuf message GenesisState { - repeated Account accounts = 1 [(gogoproto.nullable) = false]; + // previously stored accounts containing fractional balances. + reserved 1; Params params = 2 [(gogoproto.nullable) = false]; } ``` -## Account - -An `Account` is a struct representing the excess `akava` balance of an address. - -Since an address's total `akava` balance is derived from its `ukava` balance and the excess `akava` balance stored by the `Account` struct, the `akava` balance here should never exceed 1 `ukava` (10^12 `akava`). - -```protobuf -message Account { - bytes address = 1; - string balance = 2; -} -``` - ## Deployed Cosmos Coin Contract Addresses Addresses for the ERC20 contracts representing cosmos-sdk `Coin`s are kept in the module store. They are stored as bytes by the cosmos-sdk denom they represent. diff --git a/x/evmutil/spec/README.md b/x/evmutil/spec/README.md index 0b23cf51..7330d293 100644 --- a/x/evmutil/spec/README.md +++ b/x/evmutil/spec/README.md @@ -21,13 +21,6 @@ parent: The evmutil module provides additional functionalities on top of the evm module. -### EVM `akava` Usage - -evmutil stores additional state data for evm accounts and exposes an `EvmBankKeeper` that should be used by the `x/evm` keeper for bank operations. -The purpose of the `EvmBankKeeper` is to allow the usage of the `akava` balance on the EVM via an account's existing `ukava` balance. This is needed because the EVM gas token use 18 decimals, and since `ukava` has 6 decimals, it cannot be used as the EVM gas denom directly. - -For additional details on how balance conversions work, see **[Concepts](01_concepts.md)**. - ### ERC20 Token <> sdk.Coin Conversion evmutil exposes messages to allow for the conversion of Kava ERC20 tokens and sdk.Coins via a whitelist. diff --git a/x/evmutil/testutil/suite.go b/x/evmutil/testutil/suite.go index c51453a8..a5407fe5 100644 --- a/x/evmutil/testutil/suite.go +++ b/x/evmutil/testutil/suite.go @@ -51,7 +51,6 @@ type Suite struct { BankKeeper bankkeeper.Keeper AccountKeeper authkeeper.AccountKeeper Keeper keeper.Keeper - EvmBankKeeper keeper.EvmBankKeeper Addrs []sdk.AccAddress EvmModuleAddr sdk.AccAddress QueryClient types.QueryClient @@ -69,7 +68,6 @@ func (suite *Suite) SetupTest() { suite.BankKeeper = tApp.GetBankKeeper() suite.AccountKeeper = tApp.GetAccountKeeper() suite.Keeper = tApp.GetEvmutilKeeper() - suite.EvmBankKeeper = keeper.NewEvmBankKeeper(tApp.GetEvmutilKeeper(), suite.BankKeeper, suite.AccountKeeper) suite.EvmModuleAddr = suite.AccountKeeper.GetModuleAddress(evmtypes.ModuleName) // test evm user keys that have no minting permissions diff --git a/x/evmutil/types/expected_keepers.go b/x/evmutil/types/expected_keepers.go index 31b4e4aa..1992f5d6 100644 --- a/x/evmutil/types/expected_keepers.go +++ b/x/evmutil/types/expected_keepers.go @@ -19,7 +19,11 @@ type AccountKeeper interface { // BankKeeper defines the expected bank keeper interface type BankKeeper interface { - evmtypes.BankKeeper + GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin + SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error + SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error + MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error + BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error GetSupply(ctx sdk.Context, denom string) sdk.Coin SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins diff --git a/x/evmutil/types/msg.go b/x/evmutil/types/msg.go index 441c4f81..eec759de 100644 --- a/x/evmutil/types/msg.go +++ b/x/evmutil/types/msg.go @@ -214,7 +214,7 @@ func (MsgConvertCosmosCoinToERC20) Route() string { return RouterKey } // Type implements legacytx.LegacyMsg func (MsgConvertCosmosCoinToERC20) Type() string { return TypeMsgConvertCosmosCoinToERC20 } -// NewMsgConvertCosmosCoinToERC20 returns a new MsgConvertCosmosCoinToERC20 +// NewMsgConvertCosmosCoinFromERC20 returns a new MsgConvertCosmosCoinToERC20 func NewMsgConvertCosmosCoinFromERC20( initiator string, receiver string, diff --git a/x/precisebank/README.md b/x/precisebank/README.md new file mode 100644 index 00000000..4f83d9d4 --- /dev/null +++ b/x/precisebank/README.md @@ -0,0 +1,650 @@ +# `x/precisebank` + +## Abstract + +This document specifies the precisebank module of Kava. + +The precisebank module is responsible for extending the precision of `x/bank`, intended to be used for the `x/evm`. It serves as a wrapper of `x/bank` to increase the precision of KAVA from 6 to 18 decimals, while preserving the behavior of existing `x/bank` balances. + +This module is used only by `x/evm` where 18 decimal points are expected. + +## Contents + +- [Background](#background) + - [Adding](#adding) + - [Subtracting](#subtracting) + - [Transfer](#transfer) + - [Setup](#setup) + - [Remainder does not change](#remainder-does-not-change) + - [Reserve](#reserve) + - [Burn](#burn) + - [Mint](#mint) +- [State](#state) +- [Keepers](#keepers) +- [Messages](#messages) +- [Events](#events) + - [Keeper Events](#keeper-events) + - [SendCoins](#sendcoins) + - [MintCoins](#mintcoins) + - [BurnCoins](#burncoins) +- [Client](#client) + - [gRPC](#grpc) + - [TotalFractionalBalances](#totalfractionalbalances) + - [Remainder](#remainder) + - [FractionalBalance](#fractionalbalance) + +## Background + +The standard unit of currency on the Kava Chain is `KAVA`. This is denominated by the atomic unit `ukava`, which represents $10^{-6}$ `KAVA` and there are $10^6$ `ukava` per `KAVA`. + +In order to support 18 decimals of precision while maintaining `ukava` as the cosmos-native atomic unit, we further split each `ukava` unit into $10^{12}$ `akava` units, the native currency of the Kava EVM. + +This gives a full $10^{18}$ precision on the EVM. In order to avoid confusion with atomic `ukava` units, we will refer to `akava` as "sub-atomic units". + +To review we have: + - `ukava`, the cosmos-native unit and atomic unit of the Kava chain + - `akava`, the evm-native unit and sub-atomic unit of the Kava chain + +In order to maintain consistency between the `akava` supply and the `ukava` supply, we add the constraint that each sub-atomic `akava`, may only exist as part of an atomic `ukava`. Every `akava` is fully backed by a `ukava` in the `x/bank` module. + +This is a requirement since `ukava` balances in `x/bank` are shared between the cosmos modules and the EVM. We are wrapping and extending the `x/bank` module with the `x/precisebank` module to add an extra $10^{12}$ units of precision. If $10^{12}$ `akava` is transferred in the EVM, the cosmos modules will see a 1 `ukava` transfer and vice versa. If `akava` was not fully backed by `ukava`, then balance changes would not be fully consistent across the cosmos and the EVM. + +This brings us to how account balances are extended to represent `akava` balances larger than $10^{12}$. First, we define $a(n)$, $b(n)$, and $C$ where $a(n)$ is the `akava` balance of account `n`, $b(n)$ is the `ukava` balance of account `n` stored in the `x/bank` module, and $C$ is the conversion factor equal to $10^{12}$. + +Any $a(n)$ divisible by $C$, can be represented by $C$ * $b(n)$. Any remainder not divisible by $C$, we define the "fractional balance" as $f(n)$ and store this in the `x/precisebank` store. + +Thus, + +$$a(n) = b(n) \cdot C + f(n)$$ + +where + +$$0 \le f(n) < C$$ + +$$a(n), b(n) \ge 0$$ + +This is the quotient-remainder theorem and any $a(n)$ can be represented by unique integers $b(n)$, $f(n)$ where + +$$b(n) = \lfloor a(n)/C \rfloor$$ + +$$f(n) = a(n)\bmod{C}$$ + +With this definition in mind we will refer to $b(n)$ units as integer units, and $f(n)$ as fractional units. + +Now since $f(n)$ is stored in the `x/precisebank` and not tracked by the `x/bank` keeper, these are not counted in the `ukava` supply, so if we define + +$$T_a \equiv \sum_{n \in \mathcal{A}}{a(n)}$$ + +$$T_b \equiv \sum_{n \in \mathcal{A}}{b(n)}$$ + +where $\mathcal{A}$ is the set of all accounts, $T_a$ is the total `akava` supply, and $T_b$ is the total `ukava` supply, then a reserve account $R$ is added such that + +$$a(R) = 0$$ + +$$b(R) \cdot C = \sum_{n \in \mathcal{A}}{f(n)} + r$$ + +where $R$ is the module account of the `x/precisebank`, and $r$ is the remainder or fractional amount backed by $b(R)$, but not yet in circulation such that + +$$T_a = T_b \cdot C - r$$ + +and + +$$ 0 <= r < C$$ + +We see that $0 \le T_b \cdot C - T_a < C$. If we mint, burn, or transfer `akava` such that this inequality would be invalid after updates to account balances, we adjust the $T_b$ supply by minting or burning to the reserve account which holds `ukava` equal to that of all `akava` balances less than `C` plus the remainder. + +If we didn't add these constraints, then the total supply of `ukava` reported by the bank keeper would not account for the `akava` units. We would incorrectly increase the supply of `akava` without increasing the reported total supply of KAVA. + +### Adding + +When adding we have + +$$a'(n) = a(n) + a$$ + +$$b'(n) \cdot C + f'(n) = b(n) \cdot C + f(n) + a$$ + +where $a'(n)$ is the new `akava` balance after adding `akava` amount $a$. These +must hold true for all $a$. We can determine the new $b'(n)$ and $f'(n)$ with the following formula. + +$$f'(n) = f(n) + a \mod{C}$$ + +$$b'(n) = \begin{cases} b(n) + \lfloor a/C \rfloor & f'(n) \geq f(n) \\ +b(n) + \lfloor a/C \rfloor + 1 & f'(n) < f(n) \end{cases}$$ + +We can see that $b'(n)$ is incremented by an additional 1 integer unit if +$f'(n) < f(n)$ because the new balance requires an arithmetic carry from the +fractional to the integer unit. + +### Subtracting + +When subtracting we have + +$$a'(n) = a(n) - a$$ + +$$b'(n) \cdot C + f'(n) = b(n) \cdot C + f(n) - a$$ + +and + +$$f'(n) = f(n) - a \mod{C}$$ + +$$b'(n) = \begin{cases} b(n) - \lfloor a/C \rfloor & f'(n) \leq f(n) \\ +b(n) - \lfloor a/C \rfloor - 1 & f'(n) > f(n) \end{cases}$$ + +Similar to the adding case, we subtract $b'(n)$ by an additional 1 if +$f'(n) > f(n)$ because $f(n)$ is insufficient on its own and requires an +arithmetic borrow from the integer units. + +### Transfer + +A transfer is a combination of adding and subtracting of a single amount between +two different accounts. The transfer is valid if both the subtraction for the +sender and the addition for the receiver are valid. + +#### Setup + +Let two accounts $1$ and $2$ have balances $a(1)$ and $a(2)$, and $a$ is the +amount to transfer. Assume that $a(1) \ge a$ to ensure that the transfer is +valid. We initiate a transfer by subtracting $a$ from account $1$ and adding $a$ +to account $2$, yielding + +$$a'(1) = a(1) - a$$ + +$$a'(2) = a(2) + a$$ + +The reserve account must also be updated to reflect the change in the total +supply of fractional units. + +$$b(R) \cdot C = \sum_{n \in \mathcal{A}}{f(n)} + r$$ + +$$b'(R) \cdot C = \sum_{n \in \mathcal{A}}{f'(n)} + r'$$ + +With these two formulas, we can determine the new remainder and reserve by using +the delta of the sum of fractional units and the remainder. + +$$(b'(R)-b(R)) \cdot C = \sum_{n \in \mathcal{A}}{f'(n)} - \sum_{n \in \mathcal{A}}{f(n)} + r' - r$$ + +Since only two accounts are involved in the transfer, we can use the two account +balances in place of the fractional sum delta. + +$$(b'(R)-b(R)) \cdot C = f'(1) - f(1) + f'(2) - f(2) + r' - r$$ + +#### Remainder does not change + +Take $\mod{C}$ of both sides of the equation. + +$$(b'(R)-b(R)) \cdot C \mod{C} = [f'(1) - f(1) + f'(2) - f(2) + r' - r] \mod{C}$$ + +Since $C$ is a multiple of $C$, the left side of the equation is $0$. + +$$0 = f'(1) - f(1) + f'(2) - f(2) + r' - r \mod{C}$$ + +Replace $f'(1)$ and $f'(2)$ with their definitions in terms of $f(1)$ and $f(2)$. + +$$0 = (f(1) - a)\bmod{C} - f(1) + (f(2) + a)\bmod{C} - f(2) + r' - r \mod{C}$$ + +This can be simplified to: + +$$0 = f(1) - a - f(1) + f(2) + a - f(2) + r' - r \mod{C}$$ + +Canceling out terms $a$, $f(1)$ and $f(2)$. + +$$0 = r' - r \mod{C}$$ + +By the quotient remainder theorem, we can express $r' - r$ as: + +$$q * C = r' - r$$ + +for some integer $q$. + +With our known range of $r$ and $r'$: + +$$0 \leq r' < C, 0 \leq r < C$$ + +We can see that $r' - r$ must be in the range + +$$ -C < r' - r < C$$ + +This implies that $q$ must be $0$ as there is no other integer $q$ that satisfies the inequality. + +$$ -C < q * C < C$$ + +$$q = 0$$ + +$$ r' - r = 0$$ + +Therefore, the remainder does not change during a transfer. + +#### Reserve + +The reserve account must be updated to reflect the change in the total supply of fractional units. + +The change in reserve is determined by the change in the fractional units of the two accounts. + +$$(b'(R)-b(R)) \cdot C = f'(1) - f(1) + f'(2) - f(2)$$ + +For $f'(1)$, we can represent the new fractional balance as: + +$$f'(1) = f(1) - a \mod{C}$$ + +$$f'(1)\bmod{C}= f(1)\bmod{C} - a \bmod{C} \mod{C}$$ + +$$f'(1) = f(1) - a \bmod{C} \mod{C}$$ + +This results in two cases for $f'(1)$: + +$$f'(1) = \begin{cases} f(1) - a\bmod{C} & 0 \leq f(1) - a\bmod{C} \\ +f(1) - a\bmod{C} + C & 0 > f(1) - a\bmod{C} \end{cases}$$ + +Since we can identify the following: + +$$f'(1) \leq f(1) \Longleftrightarrow f'(1) = f(1) - a\bmod{C} $$ + +$$f'(1) > f(1) \Longleftrightarrow f'(1) = f(1) - a\bmod{C} + C$$ + +We can simplify the two cases for $f'(1)$: + +$$f'(1) = \begin{cases} f(1) - a\bmod{C} & f'(1) \leq f(1) \\ +f(1) - a\bmod{C} + C & f'(1) > f(1) \end{cases}$$ + +The same for $f'(2)$: + +$$f'(2) = f(2) + a \mod{C}$$ + +$$f'(2)\bmod{C}= f(2)\bmod{C} + a \bmod{C} \mod{C}$$ + +$$f'(2) = f(2) + a \bmod{C} \mod{C}$$ + +$$f'(2) = \begin{cases} f(2) + a\bmod{C} & f'(2) \geq f(2) \\ +f(2) + a\bmod{C} - C & f'(2) < f(2) \end{cases}$$ + +Bringing the two cases for the two accounts together to determine the change in the reserve account: + +$$b'(R) - b(R) \cdot C = \begin{cases} f(1) - a\bmod{C} + C - f(1) + f(2) + a\bmod{C} - C + f(2) & f'(1) > f(1) \land f'(2) < f(2) \\ +f(1) - a\bmod{C} - f(1) + f(2) + a\bmod{C} - C + f(2) & f'(1) \leq f(1) \land f'(2) < f(2) \\ +f(1) - a\bmod{C} + C - f(1) + f(2) + a\bmod{C} + f(2) & f'(1) > f(1) \land f'(2) \geq f(2) \\ +f(1) - a\bmod{C} - f(1) + f(2) + a\bmod{C} + f(2) & f'(1) \leq f(1) \land f'(2) \geq f(2) \\ +\end{cases}$$ + +This simplifies to: + +$$b'(R) - b(R) \cdot C = \begin{cases} 0 & f'(1) > f(1) \land f'(2) < f(2) \\ +-C & f'(1) \leq f(1) \land f'(2) < f(2) \\ +C & f'(1) > f(1) \land f'(2) \geq f(2) \\ +0 & f'(1) \leq f(1) \land f'(2) \geq f(2) \\ +\end{cases}$$ + +Simplifying further by dividing by $C$: + +$$b'(R) - b(R) = \begin{cases} 0 & f'(1) > f(1) \land f'(2) < f(2) \\ +-1 & f'(1) \leq f(1) \land f'(2) < f(2) \\ +1 & f'(1) > f(1) \land f'(2) \geq f(2) \\ +0 & f'(1) \leq f(1) \land f'(2) \geq f(2) \\ +\end{cases}$$ + +Thus the reserve account is updated based on the changes in the fractional units of the two accounts. + +### Burn + +When burning, we change only 1 account. Assume we are burning an amount $a$ from account $1$. + +$$a'(1) = a(1) - a$$ + +The change in reserve is determined by the change in the fractional units of the account and the remainder. + +$$(b'(R)-b(R)) \cdot C = f'(1) - f(1) + r' - r$$ + +The new fractional balance is: + +$$f'(1) = f(1) - a \mod{C}$$ + +Apply modulo $C$ to both sides of the equation. + +$$f'(1)\bmod{C}= f(1)\bmod{C} - a \bmod{C} \mod{C}$$ + +This simplifies to: + +$$f'(1) = f(1) - a \bmod{C} \mod{C}$$ + +We can see two cases for $f'(1)$, depending on whether the new fractional balance is less than the old fractional balance. + +$$f'(1) = \begin{cases} f(1) - a\bmod{C} & f'(1) \leq f(1) \\ +f(1) - a\bmod{C} + C & f'(1) > f(1) \end{cases}$$ + +The second case occurs when we need to borrow from the integer units. + +We update the remainder by adding $a$ to $r$ as burning increases the amount no longer in circulation but still backed by the reserve. + +$$r' = r + a \mod{C}$$ + +$$r'\bmod{C}= r\bmod{C} + a \bmod{C} \mod{C}$$ + +$$r' = r + a \bmod{C} \mod{C}$$ + +We can see two cases for $r'$, depending on whether the new remainder is less than the old remainder. + +$$r' = \begin{cases} r + a\bmod{C} & r' \geq r \\ +r + a\bmod{C} - C & r' < r \end{cases}$$ + +The reserve account is updated based on the changes in the fractional units of the account and remainder. + +$$b'(R) - b(R) = \begin{cases} 0 & f'(1) > f(1) \land r' < r \\ +-1 & f'(1) \leq f(1) \land r' < r \\ +1 & f'(1) > f(1) \land r' \geq r \\ +0 & f'(1) \leq f(1) \land r' \geq r \\ +\end{cases}$$ + +### Mint + +Minting is similar to burning, but we add to the account instead of +removing it. Assume we are minting an amount $a$ to account $1$. + +$$a'(1) = a(1) + a$$ + +The change in reserve is determined by the change in the fractional units of the account and the remainder. + +$$(b'(R)-b(R)) \cdot C = f'(1) - f(1) + r' - r$$ + +The new fractional balance is: + +$$f'(1) = f(1) + a \mod{C}$$ + +Apply modulo $C$ to both sides of the equation. + +$$f'(1)\bmod{C}= f(1)\bmod{C} + a \bmod{C} \mod{C}$$ + +$$f'(1) = f(1) + a \bmod{C} \mod{C}$$ + +We can see two cases for $f'(1)$, depending on whether the new fractional balance is greater than the old fractional balance. + +$$f'(1) = \begin{cases} f(1) + a\bmod{C} & f'(1) \geq f(1) \\ +f(1) + a\bmod{C} - C & f'(1) < f(1) \end{cases}$$ + +The second case occurs when we need to carry to the integer unit. + +We update the remainder by subtracting $a$ from $r$ as minting decreases the amount no longer in circulation but still backed by the reserve. + +$$r' = r - a \mod{C}$$ + +$$r'\bmod{C}= r\bmod{C} - a \bmod{C} \mod{C}$$ + +$$r' = r - a \bmod{C} \mod{C}$$ + +$$r' = \begin{cases} r - a\bmod{C} & r' \leq r \\ +r - a\bmod{C} + C & r' > r \end{cases}$$ + +The reserve account is updated based on the changes in the fractional units of the account and the remainder. + +$$b'(R) - b(R) = \begin{cases} 0 & r' > r \land f'(1) < f(1) \\ +-1 & r' \leq r \land f'(1) < f(1) \\ +1 & r' > r \land f'(1) \geq f(1) \\ +0 & r' \leq r \land f'(1) \geq f(1) \\ +\end{cases}$$ + +## State + +The `x/precisebank` module keeps state of the following: +1. Account fractional balances. +2. Remainder amount. This amount represents the fractional amount that is backed + by the reserve account but not yet in circulation. This can be non-zero if + a fractional amount less than `1ukava` is minted. + + **Note:** Currently, mint and burns are only used to transfer fractional + amounts between accounts via `x/evm`. This means mint and burns on mainnet + state will always be equal and opposite, always resulting in a zero remainder + at the end of each transaction and block. + +The `x/precisebank` module does not keep track of the reserve as it is stored in +the `x/bank` module. + +## Keepers + +The `x/precisebank module only exposes one keeper that wraps the bank module` +keeper and implements bank keeper compatible methods to support extended coin. +This complies with the `x/evm` module interface for `BankKeeper`. + +```go +type BankKeeper interface { + authtypes.BankKeeper + SpendableCoin(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin + SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error + MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error + BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error +} +``` + +## Messages + +The `x/precisebank` module does not have any messages and is intended to be used +by other modules as a replacement of the bank module. + +## Events + +### Keeper Events + +The `x/precisebank` module emits the following events, that are meant to be +match the events emitted by the `x/bank` module. Events emitted by +`x/precisebank` will only contain `akava` amounts, as the `x/bank` module will +emit events with all other denoms. This means if an account transfers multiple +coins including `akava`, the `x/precisebank` module will emit an event with the +full `akava` amount. If `ukava` is included in a transfer, mint, or burn, the +`x/precisebank` module will emit an event with the full equivalent `akava` +amount. + +#### SendCoins + +```json +{ + "type": "transfer", + "attributes": [ + { + "key": "recipient", + "value": "{{sdk.AccAddress of the recipient}}", + "index": true + }, + { + "key": "sender", + "value": "{{sdk.AccAddress of the sender}}", + "index": true + }, + { + "key": "amount", + "value": "{{sdk.Coins being transferred}}", + "index": true + } + ] +} +``` + +```json +{ + "type": "coin_spent", + "attributes": [ + { + "key": "spender", + "value": "{{sdk.AccAddress of the address which is spending coins}}", + "index": true + }, + { + "key": "amount", + "value": "{{sdk.Coins being spent}}", + "index": true + } + ] +} +``` + +```json +{ + "type": "coin_received", + "attributes": [ + { + "key": "receiver", + "value": "{{sdk.AccAddress of the address beneficiary of the coins}}", + "index": true + }, + { + "key": "amount", + "value": "{{sdk.Coins being received}}", + "index": true + } + ] +} +``` + +#### MintCoins + +```json +{ + "type": "coinbase", + "attributes": [ + { + "key": "minter", + "value": "{{sdk.AccAddress of the module minting coins}}", + "index": true + }, + { + "key": "amount", + "value": "{{sdk.Coins being minted}}", + "index": true + } + ] +} +``` + +```json +{ + "type": "coin_received", + "attributes": [ + { + "key": "receiver", + "value": "{{sdk.AccAddress of the module minting coins}}", + "index": true + }, + { + "key": "amount", + "value": "{{sdk.Coins being received}}", + "index": true + } + ] +} +``` + +#### BurnCoins + +```json +{ + "type": "burn", + "attributes": [ + { + "key": "burner", + "value": "{{sdk.AccAddress of the module burning coins}}", + "index": true + }, + { + "key": "amount", + "value": "{{sdk.Coins being burned}}", + "index": true + } + ] +} +``` + +```json +{ + "type": "coin_spent", + "attributes": [ + { + "key": "spender", + "value": "{{sdk.AccAddress of the module burning coins}}", + "index": true + }, + { + "key": "amount", + "value": "{{sdk.Coins being burned}}", + "index": true + } + ] +} +``` + +## Client + +### gRPC + +A user can query the precisebank module using gRPC endpoints. + +#### TotalFractionalBalances + +The `TotalFractionalBalances` endpoint allows users to query the aggregate sum +of all fractional balances. This is primarily used for external verification of +the module state against the reserve balance. + +```shell +kava.precisebank.v1.Query/TotalFractionalBalances +``` + +Example: + +```shell +grpcurl -plaintext \ + localhost:9090 \ + kava.precisebank.v1.Query/TotalFractionalBalances +``` + +Example Output: + +```json +{ + "total": "2000000000000akava" +} +``` + +#### Remainder + +The `Remainder` endpoint allows users to query the current remainder amount. + +```shell +kava.precisebank.v1.Query/Remainder +``` + +Example: + +```shell +grpcurl -plaintext \ + localhost:9090 \ + kava.precisebank.v1.Query/Remainder +``` + +Example Output: + +```json +{ + "remainder": "100akava" +} +``` + +#### FractionalBalance + +The `FractionalBalance` endpoint allows users to query the fractional balance of +a specific account. + +```shell +kava.precisebank.v1.Query/FractionalBalance +``` + +Example: + +```shell +grpcurl -plaintext \ + -d '{"address": "kava1..."}' \ + localhost:9090 \ + kava.precisebank.v1.Query/FractionalBalance +``` + +Example Output: + +```json +{ + "fractional_balance": "10000akava" +} +``` diff --git a/x/precisebank/genesis.go b/x/precisebank/genesis.go new file mode 100644 index 00000000..86d3c97f --- /dev/null +++ b/x/precisebank/genesis.go @@ -0,0 +1,73 @@ +package precisebank + +import ( + "fmt" + + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/x/precisebank/keeper" + "github.com/0glabs/0g-chain/x/precisebank/types" +) + +// InitGenesis initializes the store state from a genesis state. +func InitGenesis( + ctx sdk.Context, + keeper keeper.Keeper, + ak types.AccountKeeper, + bk types.BankKeeper, + gs *types.GenesisState, +) { + // Ensure the genesis state is valid + if err := gs.Validate(); err != nil { + panic(fmt.Sprintf("failed to validate %s genesis state: %s", types.ModuleName, err)) + } + + // Initialize module account + if moduleAcc := ak.GetModuleAccount(ctx, types.ModuleName); moduleAcc == nil { + panic(fmt.Sprintf("%s module account has not been set", types.ModuleName)) + } + + // Check module balance matches sum of fractional balances + remainder + // This is always a whole integer amount, as previously verified in + // GenesisState.Validate() + totalAmt := gs.TotalAmountWithRemainder() + + moduleAddr := ak.GetModuleAddress(types.ModuleName) + moduleBal := bk.GetBalance(ctx, moduleAddr, types.IntegerCoinDenom) + moduleBalExtended := moduleBal.Amount.Mul(types.ConversionFactor()) + + // Compare balances in full precise extended amounts + if !totalAmt.Equal(moduleBalExtended) { + panic(fmt.Sprintf( + "module account balance does not match sum of fractional balances and remainder, balance is %s but expected %v%s (%v%s)", + moduleBal, + totalAmt, types.ExtendedCoinDenom, + totalAmt.Quo(types.ConversionFactor()), types.IntegerCoinDenom, + )) + } + + // Set FractionalBalances in state + for _, bal := range gs.Balances { + addr := sdk.MustAccAddressFromBech32(bal.Address) + + keeper.SetFractionalBalance(ctx, addr, bal.Amount) + } + + // Set remainder amount in state + keeper.SetRemainderAmount(ctx, gs.Remainder) +} + +// ExportGenesis returns a GenesisState for a given context and keeper. +func ExportGenesis(ctx sdk.Context, keeper keeper.Keeper) *types.GenesisState { + balances := types.FractionalBalances{} + keeper.IterateFractionalBalances(ctx, func(addr sdk.AccAddress, amount sdkmath.Int) bool { + balances = append(balances, types.NewFractionalBalance(addr.String(), amount)) + + return false + }) + + remainder := keeper.GetRemainderAmount(ctx) + + return types.NewGenesisState(balances, remainder) +} diff --git a/x/precisebank/genesis_test.go b/x/precisebank/genesis_test.go new file mode 100644 index 00000000..1e8a318a --- /dev/null +++ b/x/precisebank/genesis_test.go @@ -0,0 +1,271 @@ +package precisebank_test + +import ( + "testing" + + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/x/precisebank" + "github.com/0glabs/0g-chain/x/precisebank/keeper" + "github.com/0glabs/0g-chain/x/precisebank/testutil" + "github.com/0glabs/0g-chain/x/precisebank/types" + "github.com/stretchr/testify/suite" +) + +type GenesisTestSuite struct { + testutil.Suite +} + +func TestGenesisTestSuite(t *testing.T) { + suite.Run(t, new(GenesisTestSuite)) +} + +func (suite *GenesisTestSuite) TestInitGenesis() { + tests := []struct { + name string + setupFn func() + genesisState *types.GenesisState + panicMsg string + }{ + { + "valid - default genesisState", + func() {}, + types.DefaultGenesisState(), + "", + }, + { + "valid - empty genesisState", + func() {}, + &types.GenesisState{}, + "failed to validate precisebank genesis state: nil remainder amount", + }, + { + "valid - module balance matches non-zero amount", + func() { + // Set module account balance to expected amount + err := suite.BankKeeper.MintCoins( + suite.Ctx, + types.ModuleName, + sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdkmath.NewInt(2))), + ) + suite.Require().NoError(err) + }, + types.NewGenesisState( + types.FractionalBalances{ + types.NewFractionalBalance(sdk.AccAddress{1}.String(), types.ConversionFactor().SubRaw(1)), + types.NewFractionalBalance(sdk.AccAddress{2}.String(), types.ConversionFactor().SubRaw(1)), + }, + // 2 leftover from 0.999... + 0.999... + sdkmath.NewInt(2), + ), + "", + }, + { + // Other GenesisState.Validate() tests are in types/genesis_test.go + "invalid genesisState - GenesisState.Validate() is called", + func() {}, + types.NewGenesisState( + types.FractionalBalances{ + types.NewFractionalBalance(sdk.AccAddress{1}.String(), sdkmath.NewInt(1)), + types.NewFractionalBalance(sdk.AccAddress{1}.String(), sdkmath.NewInt(1)), + }, + sdkmath.ZeroInt(), + ), + "failed to validate precisebank genesis state: invalid balances: duplicate address 0g1qy20a4yf", + }, + { + "invalid - module balance insufficient", + func() {}, + types.NewGenesisState( + types.FractionalBalances{ + types.NewFractionalBalance(sdk.AccAddress{1}.String(), types.ConversionFactor().SubRaw(1)), + types.NewFractionalBalance(sdk.AccAddress{2}.String(), types.ConversionFactor().SubRaw(1)), + }, + // 2 leftover from 0.999... + 0.999... + sdkmath.NewInt(2), + ), + "module account balance does not match sum of fractional balances and remainder, balance is 0ua0gi but expected 2000000000000neuron (2ua0gi)", + }, + { + "invalid - module balance excessive", + func() { + // Set module account balance to greater than expected amount + err := suite.BankKeeper.MintCoins( + suite.Ctx, + types.ModuleName, + sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdkmath.NewInt(100))), + ) + suite.Require().NoError(err) + }, + types.NewGenesisState( + types.FractionalBalances{ + types.NewFractionalBalance(sdk.AccAddress{1}.String(), types.ConversionFactor().SubRaw(1)), + types.NewFractionalBalance(sdk.AccAddress{2}.String(), types.ConversionFactor().SubRaw(1)), + }, + sdkmath.NewInt(2), + ), + "module account balance does not match sum of fractional balances and remainder, balance is 100ua0gi but expected 2000000000000neuron (2ua0gi)", + }, + { + "sets module account", + func() { + // Delete the module account first to ensure it's created here + moduleAcc := suite.AccountKeeper.GetModuleAccount(suite.Ctx, types.ModuleName) + suite.AccountKeeper.RemoveAccount(suite.Ctx, moduleAcc) + + // Ensure module account is deleted in state. + // GetModuleAccount() will always return non-nil and does not + // necessarily equate to the account being stored in the account store. + suite.Require().Nil(suite.AccountKeeper.GetAccount(suite.Ctx, moduleAcc.GetAddress())) + }, + types.DefaultGenesisState(), + "", + }, + } + + for _, tc := range tests { + suite.Run(tc.name, func() { + suite.SetupTest() + tc.setupFn() + + if tc.panicMsg != "" { + suite.Require().PanicsWithValue( + tc.panicMsg, + func() { + precisebank.InitGenesis( + suite.Ctx, + suite.Keeper, + suite.AccountKeeper, + suite.BankKeeper, + tc.genesisState, + ) + }, + ) + + return + } + + suite.Require().NotPanics(func() { + precisebank.InitGenesis( + suite.Ctx, + suite.Keeper, + suite.AccountKeeper, + suite.BankKeeper, + tc.genesisState, + ) + }) + + // Ensure module account is created + moduleAcc := suite.AccountKeeper.GetModuleAccount(suite.Ctx, types.ModuleName) + suite.NotNil(moduleAcc) + suite.NotNil( + suite.AccountKeeper.GetAccount(suite.Ctx, moduleAcc.GetAddress()), + "module account should be created & stored in account store", + ) + + // Verify balances are set in state, get full list of balances in + // state to ensure they are set AND no extra balances are set + var bals []types.FractionalBalance + suite.Keeper.IterateFractionalBalances(suite.Ctx, func(addr sdk.AccAddress, bal sdkmath.Int) bool { + bals = append(bals, types.NewFractionalBalance(addr.String(), bal)) + + return false + }) + + suite.Require().ElementsMatch(tc.genesisState.Balances, bals, "balances should be set in state") + + remainder := suite.Keeper.GetRemainderAmount(suite.Ctx) + suite.Require().Equal(tc.genesisState.Remainder, remainder, "remainder should be set in state") + + // Additional verification of state via invariants + invariantFn := keeper.AllInvariants(suite.Keeper) + msg, broken := invariantFn(suite.Ctx) + suite.Require().False(broken, "invariants should not be broken after InitGenesis") + suite.Require().Empty(msg, "invariants should not return a message after InitGenesis") + }) + } +} + +func (suite *GenesisTestSuite) TestExportGenesis() { + // ExportGenesis(InitGenesis(genesisState)) == genesisState + // Must also be valid. + + tests := []struct { + name string + initGenesisState func() *types.GenesisState + }{ + { + "InitGenesis(DefaultGenesisState)", + func() *types.GenesisState { + return types.DefaultGenesisState() + }, + }, + { + "balances, no remainder", + func() *types.GenesisState { + err := suite.BankKeeper.MintCoins( + suite.Ctx, + types.ModuleName, + sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdkmath.NewInt(1))), + ) + suite.Require().NoError(err) + + return types.NewGenesisState( + types.FractionalBalances{ + types.NewFractionalBalance(sdk.AccAddress{1}.String(), types.ConversionFactor().QuoRaw(2)), + types.NewFractionalBalance(sdk.AccAddress{2}.String(), types.ConversionFactor().QuoRaw(2)), + }, + sdkmath.ZeroInt(), + ) + }, + }, + { + "balances, remainder", + func() *types.GenesisState { + err := suite.BankKeeper.MintCoins( + suite.Ctx, + types.ModuleName, + sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdkmath.NewInt(1))), + ) + suite.Require().NoError(err) + + return types.NewGenesisState( + types.FractionalBalances{ + types.NewFractionalBalance(sdk.AccAddress{1}.String(), types.ConversionFactor().QuoRaw(2)), + types.NewFractionalBalance(sdk.AccAddress{2}.String(), types.ConversionFactor().QuoRaw(2).SubRaw(1)), + }, + sdkmath.OneInt(), + ) + }, + }, + } + + for _, tc := range tests { + suite.Run(tc.name, func() { + // Reset state + suite.SetupTest() + + initGs := tc.initGenesisState() + + suite.Require().NotPanics(func() { + precisebank.InitGenesis( + suite.Ctx, + suite.Keeper, + suite.AccountKeeper, + suite.BankKeeper, + initGs, + ) + }) + + genesisState := precisebank.ExportGenesis(suite.Ctx, suite.Keeper) + suite.Require().NoError(genesisState.Validate(), "exported genesis state should be valid") + + suite.Require().Equal( + initGs, + genesisState, + "exported genesis state should equal initial genesis state", + ) + }) + } +} diff --git a/x/precisebank/keeper/burn.go b/x/precisebank/keeper/burn.go new file mode 100644 index 00000000..1eebd394 --- /dev/null +++ b/x/precisebank/keeper/burn.go @@ -0,0 +1,182 @@ +package keeper + +import ( + "fmt" + + errorsmod "cosmossdk.io/errors" + sdkmath "cosmossdk.io/math" + "github.com/0glabs/0g-chain/x/precisebank/types" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +// BurnCoins burns coins deletes coins from the balance of the module account. +// It will panic if the module account does not exist or is unauthorized. +func (k Keeper) BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error { + // Custom protection for x/precisebank, no external module should be able to + // affect reserves. + if moduleName == types.ModuleName { + panic(errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "module account %s cannot be burned from", moduleName)) + } + + // Panic errors are identical to x/bank for consistency. + acc := k.ak.GetModuleAccount(ctx, moduleName) + if acc == nil { + panic(errorsmod.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", moduleName)) + } + + if !acc.HasPermission(authtypes.Burner) { + panic(errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "module account %s does not have permissions to burn tokens", moduleName)) + } + + // Ensure the coins are valid before burning + if !amt.IsValid() { + return errorsmod.Wrap(sdkerrors.ErrInvalidCoins, amt.String()) + } + + // Get non-ExtendedCoinDenom coins + passthroughCoins := amt + + extendedAmount := amt.AmountOf(types.ExtendedCoinDenom) + if extendedAmount.IsPositive() { + // Remove ExtendedCoinDenom from the coins as it is managed by x/precisebank + removeCoin := sdk.NewCoin(types.ExtendedCoinDenom, extendedAmount) + passthroughCoins = amt.Sub(removeCoin) + } + + // Coins unmanaged by x/precisebank are passed through to x/bank + if !passthroughCoins.Empty() { + if err := k.bk.BurnCoins(ctx, moduleName, passthroughCoins); err != nil { + return err + } + } + + // Only burn extended coin if the amount is positive + if extendedAmount.IsPositive() { + if err := k.burnExtendedCoin(ctx, moduleName, extendedAmount); err != nil { + return err + } + } + + fullEmissionCoins := sdk.NewCoins(types.SumExtendedCoin(amt)) + if fullEmissionCoins.IsZero() { + return nil + } + + ctx.EventManager().EmitEvents(sdk.Events{ + banktypes.NewCoinBurnEvent(acc.GetAddress(), fullEmissionCoins), + banktypes.NewCoinSpentEvent(acc.GetAddress(), fullEmissionCoins), + }) + + return nil +} + +// burnExtendedCoin burns the fractional amount of the ExtendedCoinDenom from the module account. +func (k Keeper) burnExtendedCoin( + ctx sdk.Context, + moduleName string, + amt sdkmath.Int, +) error { + // Get the module address + moduleAddr := k.ak.GetModuleAddress(moduleName) + + // We only need the fractional balance to burn coins, as integer burns will + // return errors on insufficient funds. + prevFractionalBalance := k.GetFractionalBalance(ctx, moduleAddr) + + // Get remainder amount first to optimize direct burn. + prevRemainder := k.GetRemainderAmount(ctx) + + // ------------------------------------------------------------------------- + // Pure stateless calculations + + integerBurnAmount := amt.Quo(types.ConversionFactor()) + fractionalBurnAmount := amt.Mod(types.ConversionFactor()) + + // newFractionalBalance can be negative if fractional balance is insufficient. + newFractionalBalance := prevFractionalBalance.Sub(fractionalBurnAmount) + + // If true, fractional balance is insufficient and will require an integer + // borrow. + requiresBorrow := newFractionalBalance.IsNegative() + + // Add to new remainder with burned fractional amount. + newRemainder := prevRemainder.Add(fractionalBurnAmount) + + // If true, remainder has accumulated enough fractional amounts to burn 1 + // integer coin. + overflowingRemainder := newRemainder.GTE(types.ConversionFactor()) + + // ------------------------------------------------------------------------- + // Stateful operations for burn + + // Not enough fractional balance: + // 1. If the new remainder incurs an additional reserve burn, we can just + // burn an additional integer coin from the account directly instead as + // an optimization. + // 2. If the new remainder is still under conversion factor (no extra + // reserve burn) then we need to transfer 1 integer coin to the reserve + // for the integer borrow. + + // Case #1: (optimization) direct burn instead of borrow (reserve transfer) + // & reserve burn. No additional reserve burn would be necessary after this. + if requiresBorrow && overflowingRemainder { + newFractionalBalance = newFractionalBalance.Add(types.ConversionFactor()) + newRemainder = newRemainder.Sub(types.ConversionFactor()) + + integerBurnAmount = integerBurnAmount.AddRaw(1) + } + + // Case #2: Transfer 1 integer coin to reserve for integer borrow to ensure + // reserve fully backs the fractional amount. + if requiresBorrow && !overflowingRemainder { + newFractionalBalance = newFractionalBalance.Add(types.ConversionFactor()) + + // Transfer 1 integer coin to reserve to cover the borrowed fractional + // amount. SendCoinsFromModuleToModule will return an error if the + // module account has insufficient funds and an error with the full + // extended balance will be returned. + borrowCoin := sdk.NewCoin(types.IntegerCoinDenom, sdkmath.OneInt()) + if err := k.bk.SendCoinsFromModuleToModule( + ctx, + moduleName, + types.ModuleName, // borrowed integer is transferred to reserve + sdk.NewCoins(borrowCoin), + ); err != nil { + return k.updateInsufficientFundsError(ctx, moduleAddr, amt, err) + } + } + + // Case #3: Does not require borrow, but remainder has accumulated enough + // fractional amounts to burn 1 integer coin. + if !requiresBorrow && overflowingRemainder { + reserveBurnCoins := sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdkmath.OneInt())) + if err := k.bk.BurnCoins(ctx, types.ModuleName, reserveBurnCoins); err != nil { + return fmt.Errorf("failed to burn %s for reserve: %w", reserveBurnCoins, err) + } + + newRemainder = newRemainder.Sub(types.ConversionFactor()) + } + + // Case #4: No additional work required, no borrow needed and no additional + // reserve burn + + // Burn the integer amount - this may include the extra optimization burn + // from case #1 + if !integerBurnAmount.IsZero() { + coin := sdk.NewCoin(types.IntegerCoinDenom, integerBurnAmount) + if err := k.bk.BurnCoins(ctx, moduleName, sdk.NewCoins(coin)); err != nil { + return k.updateInsufficientFundsError(ctx, moduleAddr, amt, err) + } + } + + // Assign new fractional balance in x/precisebank + k.SetFractionalBalance(ctx, moduleAddr, newFractionalBalance) + + // Update remainder for burned fractional coins + k.SetRemainderAmount(ctx, newRemainder) + + return nil +} diff --git a/x/precisebank/keeper/burn_integration_test.go b/x/precisebank/keeper/burn_integration_test.go new file mode 100644 index 00000000..3e457b2a --- /dev/null +++ b/x/precisebank/keeper/burn_integration_test.go @@ -0,0 +1,510 @@ +package keeper_test + +import ( + "fmt" + "testing" + + sdkmath "cosmossdk.io/math" + "github.com/0glabs/0g-chain/x/precisebank/keeper" + "github.com/0glabs/0g-chain/x/precisebank/testutil" + "github.com/0glabs/0g-chain/x/precisebank/types" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + ibctransfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" + "github.com/stretchr/testify/suite" +) + +type burnIntegrationTestSuite struct { + testutil.Suite +} + +func (suite *burnIntegrationTestSuite) SetupTest() { + suite.Suite.SetupTest() +} + +func TestBurnIntegrationTest(t *testing.T) { + suite.Run(t, new(burnIntegrationTestSuite)) +} + +func (suite *burnIntegrationTestSuite) TestBurnCoins_MatchingErrors() { + // x/precisebank BurnCoins should be identical to x/bank BurnCoins to + // consumers. This test ensures that the panics & errors returned by + // x/precisebank are identical to x/bank. + + tests := []struct { + name string + recipientModule string + setupFn func() + burnAmount sdk.Coins + wantErr string + wantPanic string + }{ + { + "invalid module", + "notamodule", + func() {}, + cs(c("ukava", 1000)), + "", + "module account notamodule does not exist: unknown address", + }, + { + "no burn permissions", + // Check app.go to ensure this module has no burn permissions + authtypes.FeeCollectorName, + func() {}, + cs(c("ukava", 1000)), + "", + "module account fee_collector does not have permissions to burn tokens: unauthorized", + }, + { + "invalid amount", + // Has burn permissions so it goes to the amt check + ibctransfertypes.ModuleName, + func() {}, + sdk.Coins{sdk.Coin{Denom: "ukava", Amount: sdkmath.NewInt(-100)}}, + "-100ukava: invalid coins", + "", + }, + { + "insufficient balance - empty", + ibctransfertypes.ModuleName, + func() {}, + cs(c("ukava", 1000)), + "spendable balance is smaller than 1000ukava: insufficient funds", + "", + }, + } + + for _, tt := range tests { + suite.Run(tt.name, func() { + // Reset + suite.SetupTest() + + if tt.wantErr == "" && tt.wantPanic == "" { + suite.Fail("test must specify either wantErr or wantPanic") + } + + if tt.wantErr != "" { + // Check x/bank BurnCoins for identical error + bankErr := suite.BankKeeper.BurnCoins(suite.Ctx, tt.recipientModule, tt.burnAmount) + suite.Require().Error(bankErr) + suite.Require().EqualError(bankErr, tt.wantErr, "expected error should match x/bank BurnCoins error") + + pbankErr := suite.Keeper.BurnCoins(suite.Ctx, tt.recipientModule, tt.burnAmount) + suite.Require().Error(pbankErr) + // Compare strings instead of errors, as error stack is still different + suite.Require().Equal( + bankErr.Error(), + pbankErr.Error(), + "x/precisebank error should match x/bank BurnCoins error", + ) + } + + if tt.wantPanic != "" { + // First check the wantPanic string is correct. + // Actually specify the panic string in the test since it makes + // it more clear we are testing specific and different cases. + suite.Require().PanicsWithError(tt.wantPanic, func() { + _ = suite.BankKeeper.BurnCoins(suite.Ctx, tt.recipientModule, tt.burnAmount) + }, "expected panic error should match x/bank BurnCoins") + + suite.Require().PanicsWithError(tt.wantPanic, func() { + _ = suite.Keeper.BurnCoins(suite.Ctx, tt.recipientModule, tt.burnAmount) + }, "x/precisebank panic should match x/bank BurnCoins") + } + }) + } +} + +func (suite *burnIntegrationTestSuite) TestBurnCoins() { + tests := []struct { + name string + startBalance sdk.Coins + burnCoins sdk.Coins + wantBalance sdk.Coins + wantErr string + }{ + { + "passthrough - unrelated", + cs(c("meow", 1000)), + cs(c("meow", 1000)), + cs(), + "", + }, + { + "passthrough - integer denom", + cs(c(types.IntegerCoinDenom, 2000)), + cs(c(types.IntegerCoinDenom, 1000)), + cs(c(types.ExtendedCoinDenom, 1000000000000000)), + "", + }, + { + "fractional only - no borrow", + cs(c(types.ExtendedCoinDenom, 1000)), + cs(c(types.ExtendedCoinDenom, 500)), + cs(c(types.ExtendedCoinDenom, 500)), + "", + }, + { + "fractional burn - borrows", + cs(ci(types.ExtendedCoinDenom, types.ConversionFactor().AddRaw(100))), + cs(c(types.ExtendedCoinDenom, 500)), + cs(ci(types.ExtendedCoinDenom, types.ConversionFactor().SubRaw(400))), + "", + }, + { + "error - insufficient integer balance", + cs(ci(types.ExtendedCoinDenom, types.ConversionFactor())), + cs(ci(types.ExtendedCoinDenom, types.ConversionFactor().MulRaw(2))), + cs(), + // Returns correct error with akava balance (rewrites Bank BurnCoins err) + "spendable balance 1000000000000akava is smaller than 2000000000000akava: insufficient funds", + }, + { + "error - insufficient fractional, borrow", + cs(c(types.ExtendedCoinDenom, 1000)), + cs(c(types.ExtendedCoinDenom, 2000)), + cs(), + // Error from SendCoins to reserve + "spendable balance 1000akava is smaller than 2000akava: insufficient funds", + }, + } + + for _, tt := range tests { + suite.Run(tt.name, func() { + // Reset + suite.SetupTest() + + moduleName := ibctransfertypes.ModuleName + recipientAddr := suite.AccountKeeper.GetModuleAddress(moduleName) + + // Start balance + err := suite.Keeper.MintCoins(suite.Ctx, moduleName, tt.startBalance) + suite.Require().NoError(err) + + // Burn + err = suite.Keeper.BurnCoins(suite.Ctx, moduleName, tt.burnCoins) + if tt.wantErr != "" { + suite.Require().Error(err) + suite.Require().EqualError(err, tt.wantErr) + return + } + + suite.Require().NoError(err) + + // ------------------------------------------------------------- + // Check FULL balances + // x/bank balances + x/precisebank balance + // Exclude "ukava" as x/precisebank balance will include it + afterBalance := suite.GetAllBalances(recipientAddr) + + suite.Require().Equal( + tt.wantBalance.String(), + afterBalance.String(), + "unexpected balance after minting %s to %s", + ) + + // Ensure reserve is backing all minted fractions + allInvariantsFn := keeper.AllInvariants(suite.Keeper) + res, stop := allInvariantsFn(suite.Ctx) + suite.Require().False(stop, "invariant should not be broken") + suite.Require().Empty(res, "unexpected invariant message: %s", res) + + intCoinAmt := tt.burnCoins.AmountOf(types.IntegerCoinDenom). + Mul(types.ConversionFactor()) + + fraCoinAmt := tt.burnCoins.AmountOf(types.ExtendedCoinDenom) + + totalExtCoinAmt := intCoinAmt.Add(fraCoinAmt) + spentCoins := sdk.NewCoins(sdk.NewCoin( + types.ExtendedCoinDenom, + totalExtCoinAmt, + )) + + events := suite.Ctx.EventManager().Events() + + expBurnEvent := banktypes.NewCoinBurnEvent(recipientAddr, spentCoins) + expSpendEvent := banktypes.NewCoinSpentEvent(recipientAddr, spentCoins) + + if totalExtCoinAmt.IsZero() { + suite.Require().NotContains(events, expBurnEvent) + suite.Require().NotContains(events, expSpendEvent) + } else { + suite.Require().Contains(events, expBurnEvent) + suite.Require().Contains(events, expSpendEvent) + } + }) + } +} + +func (suite *burnIntegrationTestSuite) TestBurnCoins_Remainder() { + // This tests a series of small burns to ensure the remainder is both + // updated correctly and reserve is correctly updated. This only burns from + // 1 single account. + + reserveAddr := suite.AccountKeeper.GetModuleAddress(types.ModuleName) + + moduleName := ibctransfertypes.ModuleName + moduleAddr := suite.AccountKeeper.GetModuleAddress(moduleName) + + startCoins := cs(ci(types.ExtendedCoinDenom, types.ConversionFactor().MulRaw(5))) + + // Start balance + err := suite.Keeper.MintCoins( + suite.Ctx, + moduleName, + startCoins, + ) + suite.Require().NoError(err) + + burnAmt := types.ConversionFactor().QuoRaw(10) + burnCoins := cs(ci(types.ExtendedCoinDenom, burnAmt)) + + // Burn 0.1 until balance is 0 + for { + reserveBalBefore := suite.BankKeeper.GetBalance( + suite.Ctx, + reserveAddr, + types.IntegerCoinDenom, + ) + + balBefore := suite.Keeper.GetBalance( + suite.Ctx, + moduleAddr, + types.ExtendedCoinDenom, + ) + remainderBefore := suite.Keeper.GetRemainderAmount(suite.Ctx) + + // ---------------------------------------- + // Burn + err := suite.Keeper.BurnCoins( + suite.Ctx, + moduleName, + burnCoins, + ) + suite.Require().NoError(err) + + // ---------------------------------------- + // Checks + remainderAfter := suite.Keeper.GetRemainderAmount(suite.Ctx) + balAfter := suite.Keeper.GetBalance( + suite.Ctx, + moduleAddr, + types.ExtendedCoinDenom, + ) + reserveBalAfter := suite.BankKeeper.GetBalance( + suite.Ctx, + reserveAddr, + types.IntegerCoinDenom, + ) + + suite.Require().Equal( + balBefore.Amount.Sub(burnAmt).String(), + balAfter.Amount.String(), + "balance should decrease by burn amount", + ) + + // Remainder should be updated correctly + suite.Require().Equal( + remainderBefore.Add(burnAmt).Mod(types.ConversionFactor()), + remainderAfter, + ) + + // If remainder has exceeded (then rolled over), reserve should be updated + if remainderAfter.LT(remainderBefore) { + suite.Require().Equal( + reserveBalBefore.Amount.SubRaw(1).String(), + reserveBalAfter.Amount.String(), + "reserve should decrease by 1 if remainder exceeds ConversionFactor", + ) + } + + // No more to burn + if balAfter.Amount.IsZero() { + break + } + } + + // Run Invariants to ensure remainder is backing all fractions correctly + res, stop := keeper.AllInvariants(suite.Keeper)(suite.Ctx) + suite.Require().False(stop, "invariant should not be broken") + suite.Require().Empty(res, "unexpected invariant message: %s", res) +} + +func (suite *burnIntegrationTestSuite) TestBurnCoins_Spread_Remainder() { + // This tests a series of small burns to ensure the remainder is both + // updated correctly and reserve is correctly updated. This burns from + // a series of multiple accounts, to test when the remainder is modified + // by multiple accounts. + + reserveAddr := suite.AccountKeeper.GetModuleAddress(types.ModuleName) + burnerModuleName := ibctransfertypes.ModuleName + burnerAddr := suite.AccountKeeper.GetModuleAddress(burnerModuleName) + + accCount := 20 + startCoins := cs(ci(types.ExtendedCoinDenom, types.ConversionFactor().MulRaw(5))) + + addrs := []sdk.AccAddress{} + + for i := 0; i < accCount; i++ { + addr := sdk.AccAddress(fmt.Sprintf("addr%d", i)) + suite.MintToAccount(addr, startCoins) + + addrs = append(addrs, addr) + } + + burnAmt := types.ConversionFactor().QuoRaw(10) + burnCoins := cs(ci(types.ExtendedCoinDenom, burnAmt)) + + // Burn 0.1 from each account + for _, addr := range addrs { + reserveBalBefore := suite.BankKeeper.GetBalance( + suite.Ctx, + reserveAddr, + types.IntegerCoinDenom, + ) + + balBefore := suite.Keeper.GetBalance( + suite.Ctx, + addr, + types.ExtendedCoinDenom, + ) + remainderBefore := suite.Keeper.GetRemainderAmount(suite.Ctx) + + // ---------------------------------------- + // Send & Burn + err := suite.Keeper.SendCoins( + suite.Ctx, + addr, + burnerAddr, + burnCoins, + ) + suite.Require().NoError(err) + + err = suite.Keeper.BurnCoins( + suite.Ctx, + burnerModuleName, + burnCoins, + ) + suite.Require().NoError(err) + + // ---------------------------------------- + // Checks + remainderAfter := suite.Keeper.GetRemainderAmount(suite.Ctx) + balAfter := suite.Keeper.GetBalance( + suite.Ctx, + addr, + types.ExtendedCoinDenom, + ) + reserveBalAfter := suite.BankKeeper.GetBalance( + suite.Ctx, + reserveAddr, + types.IntegerCoinDenom, + ) + + suite.Require().Equal( + balBefore.Amount.Sub(burnAmt).String(), + balAfter.Amount.String(), + "balance should decrease by burn amount", + ) + + // Remainder should be updated correctly + suite.Require().Equal( + remainderBefore.Add(burnAmt).Mod(types.ConversionFactor()), + remainderAfter, + ) + + suite.T().Logf("acc: %s", string(addr.Bytes())) + suite.T().Logf("acc bal: %s -> %s", balBefore, balAfter) + suite.T().Logf("remainder: %s -> %s", remainderBefore, remainderAfter) + suite.T().Logf("reserve: %v -> %v", reserveBalBefore, reserveBalAfter) + + // Reserve will change when: + // 1. Account needs to borrow from integer (transfers to reserve) + // 2. Remainder meets or exceeds conversion factor (burn 1 from reserve) + reserveIncrease := sdkmath.ZeroInt() + + // Does account need to borrow from integer? + if balBefore.Amount.Mod(types.ConversionFactor()).LT(burnAmt) { + reserveIncrease = reserveIncrease.AddRaw(1) + } + + // If remainder has exceeded (then rolled over), burn additional 1 + if remainderBefore.Add(burnAmt).GTE(types.ConversionFactor()) { + reserveIncrease = reserveIncrease.SubRaw(1) + } + + suite.Require().Equal( + reserveBalBefore.Amount.Add(reserveIncrease).String(), + reserveBalAfter.Amount.String(), + "reserve should be updated by remainder and borrowing", + ) + + // Run Invariants to ensure remainder is backing all fractions correctly + res, stop := keeper.AllInvariants(suite.Keeper)(suite.Ctx) + suite.Require().False(stop, "invariant should not be broken") + suite.Require().Empty(res, "unexpected invariant message: %s", res) + } +} + +func FuzzBurnCoins(f *testing.F) { + f.Add(int64(0)) + f.Add(int64(100)) + f.Add(types.ConversionFactor().Int64()) + f.Add(types.ConversionFactor().MulRaw(5).Int64()) + f.Add(types.ConversionFactor().MulRaw(2).AddRaw(123948723).Int64()) + + f.Fuzz(func(t *testing.T, amount int64) { + // No negative amounts + if amount < 0 { + amount = -amount + } + + // Manually setup test suite since no direct Fuzz support in test suites + suite := new(burnIntegrationTestSuite) + suite.SetT(t) + suite.SetS(suite) + suite.SetupTest() + + burnCount := int64(10) + + // Has both mint & burn permissions + moduleName := ibctransfertypes.ModuleName + recipientAddr := suite.AccountKeeper.GetModuleAddress(moduleName) + + // Start balance + err := suite.Keeper.MintCoins( + suite.Ctx, + moduleName, + cs(ci(types.ExtendedCoinDenom, sdkmath.NewInt(amount).MulRaw(burnCount))), + ) + suite.Require().NoError(err) + + // Burn multiple times to ensure different balance scenarios + for i := int64(0); i < burnCount; i++ { + err := suite.Keeper.BurnCoins( + suite.Ctx, + moduleName, + cs(c(types.ExtendedCoinDenom, amount)), + ) + suite.Require().NoError(err) + } + + // Check FULL balances + balAfter := suite.Keeper.GetBalance(suite.Ctx, recipientAddr, types.ExtendedCoinDenom) + + suite.Require().Equalf( + int64(0), + balAfter.Amount.Int64(), + "all coins should be burned, got %d", + balAfter.Amount.Int64(), + ) + + // Run Invariants to ensure remainder is backing all fractions correctly + allInvariantsFn := keeper.AllInvariants(suite.Keeper) + res, stop := allInvariantsFn(suite.Ctx) + suite.Require().False(stop, "invariant should not be broken") + suite.Require().Empty(res, "unexpected invariant message: %s", res) + }) +} diff --git a/x/precisebank/keeper/burn_test.go b/x/precisebank/keeper/burn_test.go new file mode 100644 index 00000000..6d71c361 --- /dev/null +++ b/x/precisebank/keeper/burn_test.go @@ -0,0 +1,161 @@ +package keeper_test + +import ( + "fmt" + "testing" + + "github.com/0glabs/0g-chain/x/precisebank/types" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/stretchr/testify/require" +) + +// Testing module name for mocked GetModuleAccount() +const burnerModuleName = "burner-module" + +func TestBurnCoins_PanicValidations(t *testing.T) { + // panic tests for invalid inputs + + tests := []struct { + name string + recipientModule string + setupFn func(td testData) + burnAmount sdk.Coins + wantPanic string + }{ + { + "invalid module", + "notamodule", + func(td testData) { + // Make module not found + td.ak.EXPECT(). + GetModuleAccount(td.ctx, "notamodule"). + Return(nil). + Once() + }, + cs(c("ukava", 1000)), + "module account notamodule does not exist: unknown address", + }, + { + "no permission", + burnerModuleName, + func(td testData) { + td.ak.EXPECT(). + GetModuleAccount(td.ctx, burnerModuleName). + Return(authtypes.NewModuleAccount( + authtypes.NewBaseAccountWithAddress(sdk.AccAddress{1}), + burnerModuleName, + // no burn permission + )). + Once() + }, + cs(c("ukava", 1000)), + fmt.Sprintf("module account %s does not have permissions to burn tokens: unauthorized", burnerModuleName), + }, + { + "has burn permission", + burnerModuleName, + func(td testData) { + td.ak.EXPECT(). + GetModuleAccount(td.ctx, burnerModuleName). + Return(authtypes.NewModuleAccount( + authtypes.NewBaseAccountWithAddress(sdk.AccAddress{1}), + burnerModuleName, + // includes burner permission + authtypes.Burner, + )). + Once() + + // Will call x/bank BurnCoins coins + td.bk.EXPECT(). + BurnCoins(td.ctx, burnerModuleName, cs(c("ukava", 1000))). + Return(nil). + Once() + }, + cs(c("ukava", 1000)), + "", + }, + { + "disallow burning from x/precisebank", + types.ModuleName, + func(td testData) { + // No mock setup needed since this is checked before module + // account checks + }, + cs(c("ukava", 1000)), + "module account precisebank cannot be burned from: unauthorized", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + td := NewMockedTestData(t) + tt.setupFn(td) + + if tt.wantPanic != "" { + require.PanicsWithError(t, tt.wantPanic, func() { + _ = td.keeper.BurnCoins(td.ctx, tt.recipientModule, tt.burnAmount) + }) + return + } + + require.NotPanics(t, func() { + // Not testing errors, only panics for this test + _ = td.keeper.BurnCoins(td.ctx, tt.recipientModule, tt.burnAmount) + }) + }) + } +} + +func TestBurnCoins_Errors(t *testing.T) { + // returned errors, not panics + + tests := []struct { + name string + recipientModule string + setupFn func(td testData) + burnAmount sdk.Coins + wantError string + }{ + { + "invalid coins", + burnerModuleName, + func(td testData) { + // Valid module account burner + td.ak.EXPECT(). + GetModuleAccount(td.ctx, burnerModuleName). + Return(authtypes.NewModuleAccount( + authtypes.NewBaseAccountWithAddress(sdk.AccAddress{1}), + burnerModuleName, + // includes burner permission + authtypes.Burner, + )). + Once() + }, + sdk.Coins{sdk.Coin{ + Denom: "ukava", + Amount: sdk.NewInt(-1000), + }}, + "-1000ukava: invalid coins", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + td := NewMockedTestData(t) + tt.setupFn(td) + + require.NotPanics(t, func() { + err := td.keeper.BurnCoins(td.ctx, tt.recipientModule, tt.burnAmount) + + if tt.wantError != "" { + require.Error(t, err) + require.EqualError(t, err, tt.wantError) + return + } + + require.NoError(t, err) + }) + }) + } +} diff --git a/x/precisebank/keeper/fractional_balance.go b/x/precisebank/keeper/fractional_balance.go new file mode 100644 index 00000000..6eccdd86 --- /dev/null +++ b/x/precisebank/keeper/fractional_balance.go @@ -0,0 +1,109 @@ +package keeper + +import ( + "errors" + "fmt" + + sdkmath "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/x/precisebank/types" +) + +// GetFractionalBalance returns the fractional balance for an address. +func (k *Keeper) GetFractionalBalance( + ctx sdk.Context, + address sdk.AccAddress, +) sdkmath.Int { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.FractionalBalancePrefix) + + bz := store.Get(types.FractionalBalanceKey(address)) + if bz == nil { + return sdkmath.ZeroInt() + } + + var bal sdkmath.Int + if err := bal.Unmarshal(bz); err != nil { + panic(fmt.Errorf("failed to unmarshal fractional balance: %w", err)) + } + + return bal +} + +// SetFractionalBalance sets the fractional balance for an address. +func (k *Keeper) SetFractionalBalance( + ctx sdk.Context, + address sdk.AccAddress, + amount sdkmath.Int, +) { + if address.Empty() { + panic(errors.New("address cannot be empty")) + } + + if amount.IsZero() { + k.DeleteFractionalBalance(ctx, address) + return + } + + // Ensure the fractional balance is valid before setting it. Use the + // NewFractionalAmountFromInt wrapper to use its Validate() method. + if err := types.ValidateFractionalAmount(amount); err != nil { + panic(fmt.Errorf("amount is invalid: %w", err)) + } + + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.FractionalBalancePrefix) + + amountBytes, err := amount.Marshal() + if err != nil { + panic(fmt.Errorf("failed to marshal fractional balance: %w", err)) + } + + store.Set(types.FractionalBalanceKey(address), amountBytes) +} + +// DeleteFractionalBalance deletes the fractional balance for an address. +func (k *Keeper) DeleteFractionalBalance( + ctx sdk.Context, + address sdk.AccAddress, +) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.FractionalBalancePrefix) + store.Delete(types.FractionalBalanceKey(address)) +} + +// IterateFractionalBalances iterates over all fractional balances in the store +// and performs a callback function. +func (k *Keeper) IterateFractionalBalances( + ctx sdk.Context, + cb func(address sdk.AccAddress, amount sdkmath.Int) (stop bool), +) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.FractionalBalancePrefix) + + iterator := store.Iterator(nil, nil) + defer iterator.Close() + + for ; iterator.Valid(); iterator.Next() { + address := sdk.AccAddress(iterator.Key()) + + var amount sdkmath.Int + if err := amount.Unmarshal(iterator.Value()); err != nil { + panic(fmt.Errorf("failed to unmarshal fractional balance: %w", err)) + } + + if cb(address, amount) { + break + } + } +} + +// GetTotalSumFractionalBalances returns the sum of all fractional balances. +func (k *Keeper) GetTotalSumFractionalBalances(ctx sdk.Context) sdkmath.Int { + sum := sdkmath.ZeroInt() + + k.IterateFractionalBalances(ctx, func(_ sdk.AccAddress, amount sdkmath.Int) bool { + sum = sum.Add(amount) + return false + }) + + return sum +} diff --git a/x/precisebank/keeper/fractional_balance_test.go b/x/precisebank/keeper/fractional_balance_test.go new file mode 100644 index 00000000..c5521e1c --- /dev/null +++ b/x/precisebank/keeper/fractional_balance_test.go @@ -0,0 +1,192 @@ +package keeper_test + +import ( + "testing" + + sdkmath "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + + "github.com/0glabs/0g-chain/x/precisebank/types" +) + +func TestSetGetFractionalBalance(t *testing.T) { + addr := sdk.AccAddress([]byte("test-address")) + + tests := []struct { + name string + address sdk.AccAddress + amount sdkmath.Int + setPanicMsg string + }{ + { + "valid - min amount", + addr, + sdkmath.NewInt(1), + "", + }, + { + "valid - positive amount", + addr, + sdkmath.NewInt(100), + "", + }, + { + "valid - max amount", + addr, + types.ConversionFactor().SubRaw(1), + "", + }, + { + "valid - zero amount (deletes)", + addr, + sdkmath.ZeroInt(), + "", + }, + { + "invalid - negative amount", + addr, + sdkmath.NewInt(-1), + "amount is invalid: non-positive amount -1", + }, + { + "invalid - over max amount", + addr, + types.ConversionFactor(), + "amount is invalid: amount 1000000000000 exceeds max of 999999999999", + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + td := NewMockedTestData(t) + ctx, k := td.ctx, td.keeper + + if tt.setPanicMsg != "" { + require.PanicsWithError(t, tt.setPanicMsg, func() { + k.SetFractionalBalance(ctx, tt.address, tt.amount) + }) + + return + } + + require.NotPanics(t, func() { + k.SetFractionalBalance(ctx, tt.address, tt.amount) + }) + + // If its zero balance, check it was deleted in store + if tt.amount.IsZero() { + store := prefix.NewStore(ctx.KVStore(td.storeKey), types.FractionalBalancePrefix) + bz := store.Get(types.FractionalBalanceKey(tt.address)) + require.Nil(t, bz) + + return + } + + gotAmount := k.GetFractionalBalance(ctx, tt.address) + require.Equal(t, tt.amount, gotAmount) + + // Delete balance + k.DeleteFractionalBalance(ctx, tt.address) + + store := prefix.NewStore(ctx.KVStore(td.storeKey), types.FractionalBalancePrefix) + bz := store.Get(types.FractionalBalanceKey(tt.address)) + require.Nil(t, bz) + }) + } +} + +func TestSetFractionalBalance_InvalidAddr(t *testing.T) { + tk := NewMockedTestData(t) + ctx, k := tk.ctx, tk.keeper + + require.PanicsWithError( + t, + "address cannot be empty", + func() { + k.SetFractionalBalance(ctx, sdk.AccAddress{}, sdkmath.NewInt(100)) + }, + "setting balance with empty address should panic", + ) +} + +func TestSetFractionalBalance_ZeroDeletes(t *testing.T) { + td := NewMockedTestData(t) + ctx, k := td.ctx, td.keeper + + addr := sdk.AccAddress([]byte("test-address")) + + // Set balance + k.SetFractionalBalance(ctx, addr, sdkmath.NewInt(100)) + + bal := k.GetFractionalBalance(ctx, addr) + require.Equal(t, sdkmath.NewInt(100), bal) + + // Set zero balance + k.SetFractionalBalance(ctx, addr, sdkmath.ZeroInt()) + + // Check balance was deleted + store := prefix.NewStore(ctx.KVStore(td.storeKey), types.FractionalBalancePrefix) + bz := store.Get(types.FractionalBalanceKey(addr)) + require.Nil(t, bz) + + // Set zero balance again on non-existent balance + require.NotPanics( + t, + func() { + k.SetFractionalBalance(ctx, addr, sdkmath.ZeroInt()) + }, + "deleting non-existent balance should not panic", + ) +} + +func TestIterateFractionalBalances(t *testing.T) { + tk := NewMockedTestData(t) + ctx, k := tk.ctx, tk.keeper + + addrs := []sdk.AccAddress{} + + for i := 1; i < 10; i++ { + addr := sdk.AccAddress([]byte{byte(i)}) + addrs = append(addrs, addr) + + // Set balance same as their address byte + k.SetFractionalBalance(ctx, addr, sdkmath.NewInt(int64(i))) + } + + seenAddrs := []sdk.AccAddress{} + + k.IterateFractionalBalances(ctx, func(addr sdk.AccAddress, bal sdkmath.Int) bool { + seenAddrs = append(seenAddrs, addr) + + // Balance is same as first address byte + require.Equal(t, int64(addr.Bytes()[0]), bal.Int64()) + + return false + }) + + require.ElementsMatch(t, addrs, seenAddrs, "all addresses should be seen") +} + +func TestGetAggregateSumFractionalBalances(t *testing.T) { + tk := NewMockedTestData(t) + ctx, k := tk.ctx, tk.keeper + + // Set balances from 1 to 10 + sum := sdkmath.ZeroInt() + for i := 1; i < 10; i++ { + addr := sdk.AccAddress([]byte{byte(i)}) + amt := sdkmath.NewInt(int64(i)) + + sum = sum.Add(amt) + + require.NotPanics(t, func() { + k.SetFractionalBalance(ctx, addr, amt) + }) + } + + gotSum := k.GetTotalSumFractionalBalances(ctx) + require.Equal(t, sum, gotSum) +} diff --git a/x/precisebank/keeper/grpc_query.go b/x/precisebank/keeper/grpc_query.go new file mode 100644 index 00000000..9a00d8e8 --- /dev/null +++ b/x/precisebank/keeper/grpc_query.go @@ -0,0 +1,73 @@ +package keeper + +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/x/precisebank/types" +) + +type queryServer struct { + keeper Keeper +} + +// NewQueryServerImpl creates a new server for handling gRPC queries. +func NewQueryServerImpl(k Keeper) types.QueryServer { + return &queryServer{keeper: k} +} + +var _ types.QueryServer = queryServer{} + +// TotalFractionalBalances returns the total sum of all fractional balances. +// This is mostly for external verification of the total fractional balances, +// being a multiple of the conversion factor and backed by the reserve. +func (s queryServer) TotalFractionalBalances( + goCtx context.Context, + req *types.QueryTotalFractionalBalancesRequest, +) (*types.QueryTotalFractionalBalancesResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + totalAmount := s.keeper.GetTotalSumFractionalBalances(ctx) + + totalCoin := sdk.NewCoin(types.ExtendedCoinDenom, totalAmount) + + return &types.QueryTotalFractionalBalancesResponse{ + Total: totalCoin, + }, nil +} + +// Remainder returns the remainder amount in x/precisebank. +func (s queryServer) Remainder( + goCtx context.Context, + req *types.QueryRemainderRequest, +) (*types.QueryRemainderResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + remainder := s.keeper.GetRemainderAmount(ctx) + remainderCoin := sdk.NewCoin(types.ExtendedCoinDenom, remainder) + + return &types.QueryRemainderResponse{ + Remainder: remainderCoin, + }, nil +} + +// FractionalBalance returns the fractional balance of an account. +func (s queryServer) FractionalBalance( + goCtx context.Context, + req *types.QueryFractionalBalanceRequest, +) (*types.QueryFractionalBalanceResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + address, err := sdk.AccAddressFromBech32(req.Address) + if err != nil { + return nil, err + } + + amt := s.keeper.GetFractionalBalance(ctx, address) + fractionalBalance := sdk.NewCoin(types.ExtendedCoinDenom, amt) + + return &types.QueryFractionalBalanceResponse{ + FractionalBalance: fractionalBalance, + }, nil +} diff --git a/x/precisebank/keeper/grpc_query_test.go b/x/precisebank/keeper/grpc_query_test.go new file mode 100644 index 00000000..1ab99e94 --- /dev/null +++ b/x/precisebank/keeper/grpc_query_test.go @@ -0,0 +1,171 @@ +package keeper_test + +import ( + "context" + "strconv" + "testing" + + sdkmath "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/baseapp" + sdk "github.com/cosmos/cosmos-sdk/types" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + "github.com/stretchr/testify/suite" + + "github.com/0glabs/0g-chain/x/precisebank/keeper" + "github.com/0glabs/0g-chain/x/precisebank/testutil" + "github.com/0glabs/0g-chain/x/precisebank/types" +) + +type grpcQueryTestSuite struct { + testutil.Suite + + queryClient types.QueryClient +} + +func (suite *grpcQueryTestSuite) SetupTest() { + suite.Suite.SetupTest() + + queryHelper := baseapp.NewQueryServerTestHelper(suite.Ctx, suite.App.InterfaceRegistry()) + types.RegisterQueryServer(queryHelper, keeper.NewQueryServerImpl(suite.Keeper)) + + suite.queryClient = types.NewQueryClient(queryHelper) +} + +func TestGrpcQueryTestSuite(t *testing.T) { + suite.Run(t, new(grpcQueryTestSuite)) +} + +func (suite *grpcQueryTestSuite) TestQueryTotalFractionalBalance() { + testCases := []struct { + name string + giveBalances []sdkmath.Int + }{ + { + "empty", + []sdkmath.Int{}, + }, + { + "min amount", + []sdkmath.Int{ + types.ConversionFactor().QuoRaw(2), + types.ConversionFactor().QuoRaw(2), + }, + }, + { + "exceeds conversion factor", + []sdkmath.Int{ + // 4 accounts * 0.5 == 2 + types.ConversionFactor().QuoRaw(2), + types.ConversionFactor().QuoRaw(2), + types.ConversionFactor().QuoRaw(2), + types.ConversionFactor().QuoRaw(2), + }, + }, + } + + for _, tc := range testCases { + suite.Run(tc.name, func() { + suite.SetupTest() + + total := sdk.NewCoin(types.ExtendedCoinDenom, sdkmath.ZeroInt()) + for i, balance := range tc.giveBalances { + addr := sdk.AccAddress([]byte(strconv.Itoa(i))) + suite.Keeper.SetFractionalBalance(suite.Ctx, addr, balance) + + total.Amount = total.Amount.Add(balance) + } + + res, err := suite.queryClient.TotalFractionalBalances( + context.Background(), + &types.QueryTotalFractionalBalancesRequest{}, + ) + suite.Require().NoError(err) + + suite.Require().Equal(total, res.Total) + }) + } +} + +func (suite *grpcQueryTestSuite) TestQueryRemainder() { + res, err := suite.queryClient.Remainder( + context.Background(), + &types.QueryRemainderRequest{}, + ) + suite.Require().NoError(err) + + expRemainder := sdk.NewCoin(types.ExtendedCoinDenom, sdkmath.ZeroInt()) + suite.Require().Equal(expRemainder, res.Remainder) + + // Mint fractional coins to create non-zero remainder + + pbk := suite.App.GetPrecisebankKeeper() + + coin := sdk.NewCoin(types.ExtendedCoinDenom, sdkmath.OneInt()) + err = pbk.MintCoins( + suite.Ctx, + minttypes.ModuleName, + sdk.NewCoins(coin), + ) + suite.Require().NoError(err) + + res, err = suite.queryClient.Remainder( + context.Background(), + &types.QueryRemainderRequest{}, + ) + suite.Require().NoError(err) + + expRemainder.Amount = types.ConversionFactor().Sub(coin.Amount) + suite.Require().Equal(expRemainder, res.Remainder) +} + +func (suite *grpcQueryTestSuite) TestQueryFractionalBalance() { + testCases := []struct { + name string + giveBalance sdkmath.Int + }{ + { + "zero", + sdkmath.ZeroInt(), + }, + { + "min amount", + sdkmath.OneInt(), + }, + { + "max amount", + types.ConversionFactor().SubRaw(1), + }, + { + "multiple integer amounts, 0 fractional", + types.ConversionFactor().MulRaw(5), + }, + { + "multiple integer amounts, non-zero fractional", + types.ConversionFactor().MulRaw(5).Add(types.ConversionFactor().QuoRaw(2)), + }, + } + + for _, tc := range testCases { + suite.Run(tc.name, func() { + suite.SetupTest() + + addr := sdk.AccAddress([]byte("test")) + + coin := sdk.NewCoin(types.ExtendedCoinDenom, tc.giveBalance) + suite.MintToAccount(addr, sdk.NewCoins(coin)) + + res, err := suite.queryClient.FractionalBalance( + context.Background(), + &types.QueryFractionalBalanceRequest{ + Address: addr.String(), + }, + ) + suite.Require().NoError(err) + + // Only fractional amount, even if minted more than conversion factor + expAmount := tc.giveBalance.Mod(types.ConversionFactor()) + expFractionalBalance := sdk.NewCoin(types.ExtendedCoinDenom, expAmount) + suite.Require().Equal(expFractionalBalance, res.FractionalBalance) + }) + } +} diff --git a/x/precisebank/keeper/invariants.go b/x/precisebank/keeper/invariants.go new file mode 100644 index 00000000..41e79097 --- /dev/null +++ b/x/precisebank/keeper/invariants.go @@ -0,0 +1,205 @@ +package keeper + +import ( + "fmt" + + sdkmath "cosmossdk.io/math" + "github.com/0glabs/0g-chain/x/precisebank/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// RegisterInvariants registers the x/precisebank module invariants +func RegisterInvariants( + ir sdk.InvariantRegistry, + k Keeper, + bk types.BankKeeper, +) { + ir.RegisterRoute(types.ModuleName, "reserve-backs-fractions", ReserveBacksFractionsInvariant(k)) + ir.RegisterRoute(types.ModuleName, "balance-remainder-total", BalancedFractionalTotalInvariant(k)) + ir.RegisterRoute(types.ModuleName, "valid-fractional-balances", ValidFractionalAmountsInvariant(k)) + ir.RegisterRoute(types.ModuleName, "valid-remainder-amount", ValidRemainderAmountInvariant(k)) + ir.RegisterRoute(types.ModuleName, "fractional-denom-not-in-bank", FractionalDenomNotInBankInvariant(k)) +} + +// AllInvariants runs all invariants of the X/precisebank module. +func AllInvariants(k Keeper) sdk.Invariant { + return func(ctx sdk.Context) (string, bool) { + res, stop := ReserveBacksFractionsInvariant(k)(ctx) + if stop { + return res, stop + } + + res, stop = BalancedFractionalTotalInvariant(k)(ctx) + if stop { + return res, stop + } + + res, stop = ValidFractionalAmountsInvariant(k)(ctx) + if stop { + return res, stop + } + + res, stop = ValidRemainderAmountInvariant(k)(ctx) + if stop { + return res, stop + } + + res, stop = FractionalDenomNotInBankInvariant(k)(ctx) + if stop { + return res, stop + } + + return "", false + } +} + +// ReserveBacksFractionsInvariant checks that the total amount of backing +// coins in the reserve is equal to the total amount of fractional balances, +// such that the backing is always available to redeem all fractional balances +// and there are no extra coins in the reserve that are not backing any +// fractional balances. +func ReserveBacksFractionsInvariant(k Keeper) sdk.Invariant { + return func(ctx sdk.Context) (string, bool) { + var ( + msg string + broken bool + ) + + fractionalBalSum := k.GetTotalSumFractionalBalances(ctx) + remainderAmount := k.GetRemainderAmount(ctx) + + // Get the total amount of backing coins in the reserve + moduleAddr := k.ak.GetModuleAddress(types.ModuleName) + reserveIntegerBalance := k.bk.GetBalance(ctx, moduleAddr, types.IntegerCoinDenom) + reserveExtendedBalance := reserveIntegerBalance.Amount.Mul(types.ConversionFactor()) + + // The total amount of backing coins in the reserve should be equal to + // fractional balances + remainder amount + totalRequiredBacking := fractionalBalSum.Add(remainderAmount) + + broken = !reserveExtendedBalance.Equal(totalRequiredBacking) + msg = fmt.Sprintf( + "%s reserve balance %s mismatches %s (fractional balances %s + remainder %s)\n", + types.ExtendedCoinDenom, + reserveExtendedBalance, + totalRequiredBacking, + fractionalBalSum, + remainderAmount, + ) + + return sdk.FormatInvariant( + types.ModuleName, "module reserve backing total fractional balances", + msg, + ), broken + } +} + +// ValidFractionalAmountsInvariant checks that all individual fractional +// balances are valid. +func ValidFractionalAmountsInvariant(k Keeper) sdk.Invariant { + return func(ctx sdk.Context) (string, bool) { + var ( + msg string + count int + ) + + k.IterateFractionalBalances(ctx, func(addr sdk.AccAddress, amount sdkmath.Int) bool { + if err := types.ValidateFractionalAmount(amount); err != nil { + count++ + msg += fmt.Sprintf("\t%s has an invalid fractional amount of %s\n", addr, amount) + } + + return false + }) + + broken := count != 0 + + return sdk.FormatInvariant( + types.ModuleName, "valid-fractional-balances", + fmt.Sprintf("amount of invalid fractional balances found %d\n%s", count, msg), + ), broken + } +} + +// ValidRemainderAmountInvariant checks that the remainder amount is valid. +func ValidRemainderAmountInvariant(k Keeper) sdk.Invariant { + return func(ctx sdk.Context) (string, bool) { + var ( + msg string + broken bool + ) + + remainderAmount := k.GetRemainderAmount(ctx) + + if !remainderAmount.IsZero() { + // Only validate if non-zero, as zero is default value + if err := types.ValidateFractionalAmount(remainderAmount); err != nil { + broken = true + msg = fmt.Sprintf("remainder amount is invalid: %s", err) + } + } + + return sdk.FormatInvariant( + types.ModuleName, "valid-remainder-amount", + msg, + ), broken + } +} + +// BalancedFractionalTotalInvariant checks that the sum of fractional balances +// and the remainder amount is divisible by the conversion factor without any +// leftover amount. +func BalancedFractionalTotalInvariant(k Keeper) sdk.Invariant { + return func(ctx sdk.Context) (string, bool) { + fractionalBalSum := k.GetTotalSumFractionalBalances(ctx) + remainderAmount := k.GetRemainderAmount(ctx) + + total := fractionalBalSum.Add(remainderAmount) + fractionalAmount := total.Mod(types.ConversionFactor()) + + broken := false + msg := "" + + if !fractionalAmount.IsZero() { + broken = true + msg = fmt.Sprintf( + "(sum(FractionalBalances) + remainder) %% conversionFactor should be 0 but got %v", + fractionalAmount, + ) + } + + return sdk.FormatInvariant( + types.ModuleName, "balance-remainder-total", + msg, + ), broken + } +} + +// FractionalDenomNotInBankInvariant checks that the bank does not hold any +// fractional denoms. These assets, e.g. akava, should only exist in the +// x/precisebank module as this is a decimal extension of ukava that shares +// the same total supply and is effectively the same asset. ukava held by this +// module in x/bank backs all fractional balances in x/precisebank. If akava +// somehow ends up in x/bank, then it would both break all expectations of this +// module as well as be double-counted in the total supply. +func FractionalDenomNotInBankInvariant(k Keeper) sdk.Invariant { + return func(ctx sdk.Context) (string, bool) { + extBankSupply := k.bk.GetSupply(ctx, types.ExtendedCoinDenom) + + broken := !extBankSupply.IsZero() + msg := "" + + if broken { + msg = fmt.Sprintf( + "x/bank should not hold any %v but has supply of %v", + types.ExtendedCoinDenom, + extBankSupply, + ) + } + + return sdk.FormatInvariant( + types.ModuleName, "fractional-denom-not-in-bank", + msg, + ), broken + } +} diff --git a/x/precisebank/keeper/invariants_integration_test.go b/x/precisebank/keeper/invariants_integration_test.go new file mode 100644 index 00000000..29d50269 --- /dev/null +++ b/x/precisebank/keeper/invariants_integration_test.go @@ -0,0 +1,129 @@ +package keeper_test + +import ( + "testing" + + sdkmath "cosmossdk.io/math" + "github.com/0glabs/0g-chain/x/precisebank/keeper" + "github.com/0glabs/0g-chain/x/precisebank/testutil" + "github.com/0glabs/0g-chain/x/precisebank/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/suite" +) + +type invariantsIntegrationTestSuite struct { + testutil.Suite +} + +func (suite *invariantsIntegrationTestSuite) SetupTest() { + suite.Suite.SetupTest() +} + +func TestInvariantsIntegrationTest(t *testing.T) { + suite.Run(t, new(invariantsIntegrationTestSuite)) +} + +func (suite *invariantsIntegrationTestSuite) FundReserve(amt sdkmath.Int) { + coins := sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, amt)) + err := suite.BankKeeper.MintCoins(suite.Ctx, types.ModuleName, coins) + suite.Require().NoError(err) +} + +func (suite *invariantsIntegrationTestSuite) TestReserveBackingFractionalInvariant() { + tests := []struct { + name string + setupFn func(ctx sdk.Context, k keeper.Keeper) + wantBroken bool + wantMsg string + }{ + { + "valid - empty state", + func(_ sdk.Context, _ keeper.Keeper) {}, + false, + "", + }, + { + "valid - fractional balances, no remainder", + func(ctx sdk.Context, k keeper.Keeper) { + k.SetFractionalBalance(ctx, sdk.AccAddress{1}, types.ConversionFactor().QuoRaw(2)) + k.SetFractionalBalance(ctx, sdk.AccAddress{2}, types.ConversionFactor().QuoRaw(2)) + // 1 integer backs same amount fractional + suite.FundReserve(sdk.NewInt(1)) + }, + false, + "", + }, + { + "valid - fractional balances, with remainder", + func(ctx sdk.Context, k keeper.Keeper) { + k.SetFractionalBalance(ctx, sdk.AccAddress{1}, types.ConversionFactor().QuoRaw(2)) + k.SetRemainderAmount(ctx, types.ConversionFactor().QuoRaw(2)) + // 1 integer backs same amount fractional including remainder + suite.FundReserve(sdk.NewInt(1)) + }, + false, + "", + }, + { + "invalid - no fractional balances, non-zero remainder", + func(ctx sdk.Context, k keeper.Keeper) { + k.SetRemainderAmount(ctx, types.ConversionFactor().QuoRaw(2)) + }, + true, + "precisebank: module reserve backing total fractional balances invariant\nakava reserve balance 0 mismatches 500000000000 (fractional balances 0 + remainder 500000000000)\n\n", + }, + { + "invalid - insufficient reserve backing", + func(ctx sdk.Context, k keeper.Keeper) { + amt := types.ConversionFactor().QuoRaw(2) + + // 0.5 int coins x 4 + k.SetFractionalBalance(ctx, sdk.AccAddress{1}, amt) + k.SetFractionalBalance(ctx, sdk.AccAddress{2}, amt) + k.SetFractionalBalance(ctx, sdk.AccAddress{3}, amt) + k.SetRemainderAmount(ctx, amt) + + // Needs 2 to back 0.5 x 4 + suite.FundReserve(sdk.NewInt(1)) + }, + true, + "precisebank: module reserve backing total fractional balances invariant\nakava reserve balance 1000000000000 mismatches 2000000000000 (fractional balances 1500000000000 + remainder 500000000000)\n\n", + }, + { + "invalid - excess reserve backing", + func(ctx sdk.Context, k keeper.Keeper) { + amt := types.ConversionFactor().QuoRaw(2) + + // 0.5 int coins x 4 + k.SetFractionalBalance(ctx, sdk.AccAddress{1}, amt) + k.SetFractionalBalance(ctx, sdk.AccAddress{2}, amt) + k.SetFractionalBalance(ctx, sdk.AccAddress{3}, amt) + k.SetRemainderAmount(ctx, amt) + + // Needs 2 to back 0.5 x 4 + suite.FundReserve(sdk.NewInt(3)) + }, + true, + "precisebank: module reserve backing total fractional balances invariant\nakava reserve balance 3000000000000 mismatches 2000000000000 (fractional balances 1500000000000 + remainder 500000000000)\n\n", + }, + } + + for _, tt := range tests { + suite.Run(tt.name, func() { + // Reset each time + suite.SetupTest() + + tt.setupFn(suite.Ctx, suite.Keeper) + + invariantFn := keeper.ReserveBacksFractionsInvariant(suite.Keeper) + msg, broken := invariantFn(suite.Ctx) + + if tt.wantBroken { + suite.Require().True(broken, "invariant should be broken but is not") + suite.Require().Equal(tt.wantMsg, msg) + } else { + suite.Require().Falsef(broken, "invariant should not be broken but is: %s", msg) + } + }) + } +} diff --git a/x/precisebank/keeper/invariants_test.go b/x/precisebank/keeper/invariants_test.go new file mode 100644 index 00000000..9aa086e3 --- /dev/null +++ b/x/precisebank/keeper/invariants_test.go @@ -0,0 +1,215 @@ +package keeper_test + +import ( + "testing" + + sdkmath "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/store/prefix" + storetypes "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/x/precisebank/keeper" + "github.com/0glabs/0g-chain/x/precisebank/types" + "github.com/0glabs/0g-chain/x/precisebank/types/mocks" + "github.com/stretchr/testify/require" +) + +func TestBalancedFractionalTotalInvariant(t *testing.T) { + tests := []struct { + name string + setupFn func(ctx sdk.Context, k keeper.Keeper) + wantBroken bool + wantMsg string + }{ + { + "valid - empty state", + func(_ sdk.Context, _ keeper.Keeper) {}, + false, + "", + }, + { + "valid - balances, 0 remainder", + func(ctx sdk.Context, k keeper.Keeper) { + k.SetFractionalBalance(ctx, sdk.AccAddress{1}, types.ConversionFactor().QuoRaw(2)) + k.SetFractionalBalance(ctx, sdk.AccAddress{2}, types.ConversionFactor().QuoRaw(2)) + }, + false, + "", + }, + { + "valid - balances, non-zero remainder", + func(ctx sdk.Context, k keeper.Keeper) { + k.SetFractionalBalance(ctx, sdk.AccAddress{1}, types.ConversionFactor().QuoRaw(2)) + k.SetFractionalBalance(ctx, sdk.AccAddress{2}, types.ConversionFactor().QuoRaw(2).SubRaw(1)) + + k.SetRemainderAmount(ctx, sdkmath.OneInt()) + }, + false, + "", + }, + { + "invalid - balances, 0 remainder", + func(ctx sdk.Context, k keeper.Keeper) { + k.SetFractionalBalance(ctx, sdk.AccAddress{1}, types.ConversionFactor().QuoRaw(2)) + k.SetFractionalBalance(ctx, sdk.AccAddress{2}, types.ConversionFactor().QuoRaw(2).SubRaw(1)) + }, + true, + "precisebank: balance-remainder-total invariant\n(sum(FractionalBalances) + remainder) % conversionFactor should be 0 but got 999999999999\n", + }, + { + "invalid - invalid balances, non-zero (insufficient) remainder", + func(ctx sdk.Context, k keeper.Keeper) { + k.SetFractionalBalance(ctx, sdk.AccAddress{1}, types.ConversionFactor().QuoRaw(2)) + k.SetFractionalBalance(ctx, sdk.AccAddress{2}, types.ConversionFactor().QuoRaw(2).SubRaw(2)) + k.SetRemainderAmount(ctx, sdkmath.OneInt()) + }, + true, + "precisebank: balance-remainder-total invariant\n(sum(FractionalBalances) + remainder) % conversionFactor should be 0 but got 999999999999\n", + }, + { + "invalid - invalid balances, non-zero (excess) remainder", + func(ctx sdk.Context, k keeper.Keeper) { + k.SetFractionalBalance(ctx, sdk.AccAddress{1}, types.ConversionFactor().QuoRaw(2)) + k.SetFractionalBalance(ctx, sdk.AccAddress{2}, types.ConversionFactor().QuoRaw(2).SubRaw(2)) + k.SetRemainderAmount(ctx, sdkmath.NewInt(5)) + }, + true, + "precisebank: balance-remainder-total invariant\n(sum(FractionalBalances) + remainder) % conversionFactor should be 0 but got 3\n", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Reset each time + td := NewMockedTestData(t) + + tt.setupFn(td.ctx, td.keeper) + + invariantFn := keeper.BalancedFractionalTotalInvariant(td.keeper) + msg, broken := invariantFn(td.ctx) + + if tt.wantBroken { + require.True(t, broken, "invariant should be broken but is not") + require.Equal(t, tt.wantMsg, msg) + } else { + require.False(t, broken, "invariant should not be broken but is") + } + }) + } +} + +func TestValidFractionalAmountsInvariant(t *testing.T) { + tests := []struct { + name string + setupFn func(ctx sdk.Context, k keeper.Keeper, storeKey storetypes.StoreKey) + wantBroken bool + wantMsg string + }{ + { + "valid - empty state", + func(_ sdk.Context, _ keeper.Keeper, _ storetypes.StoreKey) {}, + false, + "", + }, + { + "valid - valid balances", + func(ctx sdk.Context, k keeper.Keeper, _ storetypes.StoreKey) { + k.SetFractionalBalance(ctx, sdk.AccAddress{1}, types.ConversionFactor().QuoRaw(2)) + k.SetFractionalBalance(ctx, sdk.AccAddress{2}, types.ConversionFactor().QuoRaw(2)) + }, + false, + "", + }, + { + "invalid - exceeds max balance", + func(ctx sdk.Context, _ keeper.Keeper, storeKey storetypes.StoreKey) { + // Requires manual store manipulation so it is unlikely to have + // invalid state in practice. SetFractionalBalance will validate + // before setting. + addr := sdk.AccAddress{1} + amount := types.ConversionFactor() + + store := prefix.NewStore(ctx.KVStore(storeKey), types.FractionalBalancePrefix) + + amountBytes, err := amount.Marshal() + require.NoError(t, err) + + store.Set(types.FractionalBalanceKey(addr), amountBytes) + }, + true, + "precisebank: valid-fractional-balances invariant\namount of invalid fractional balances found 1\n\tkava1qy0xn7za has an invalid fractional amount of 1000000000000\n\n", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Reset each time + td := NewMockedTestData(t) + + tt.setupFn(td.ctx, td.keeper, td.storeKey) + + invariantFn := keeper.ValidFractionalAmountsInvariant(td.keeper) + msg, broken := invariantFn(td.ctx) + + if tt.wantBroken { + require.True(t, broken, "invariant should be broken but is not") + require.Equal(t, tt.wantMsg, msg) + } else { + require.False(t, broken, "invariant should not be broken but is") + } + }) + } +} + +func TestFractionalDenomNotInBankInvariant(t *testing.T) { + tests := []struct { + name string + setupFn func(ctx sdk.Context, bk *mocks.MockBankKeeper) + wantBroken bool + wantMsg string + }{ + { + "valid - integer denom (ukava) supply", + func(ctx sdk.Context, bk *mocks.MockBankKeeper) { + // No fractional balance in x/bank + // This also enforces there is no GetSupply() call for IntegerCoinDenom / ukava + bk.EXPECT(). + GetSupply(ctx, types.ExtendedCoinDenom). + Return(sdk.NewCoin(types.ExtendedCoinDenom, sdkmath.ZeroInt())). + Once() + }, + false, + "", + }, + { + "invalid - x/bank contains fractional denom (akava)", + func(ctx sdk.Context, bk *mocks.MockBankKeeper) { + bk.EXPECT(). + GetSupply(ctx, types.ExtendedCoinDenom). + Return(sdk.NewCoin(types.ExtendedCoinDenom, sdk.NewInt(1000))). + Once() + }, + true, + "precisebank: fractional-denom-not-in-bank invariant\nx/bank should not hold any akava but has supply of 1000akava\n", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Reset each time + td := NewMockedTestData(t) + + tt.setupFn(td.ctx, td.bk) + + invariantFn := keeper.FractionalDenomNotInBankInvariant(td.keeper) + msg, broken := invariantFn(td.ctx) + + if tt.wantBroken { + require.True(t, broken, "invariant should be broken but is not") + require.Equal(t, tt.wantMsg, msg) + } else { + require.False(t, broken, "invariant should not be broken but is") + } + }) + } +} diff --git a/x/precisebank/keeper/keeper.go b/x/precisebank/keeper/keeper.go new file mode 100644 index 00000000..d7a52900 --- /dev/null +++ b/x/precisebank/keeper/keeper.go @@ -0,0 +1,37 @@ +package keeper + +import ( + "github.com/cosmos/cosmos-sdk/codec" + storetypes "github.com/cosmos/cosmos-sdk/store/types" + + evmtypes "github.com/evmos/ethermint/x/evm/types" + + "github.com/0glabs/0g-chain/x/precisebank/types" +) + +// Enforce that Keeper implements the expected keeper interfaces +var _ evmtypes.BankKeeper = Keeper{} + +// Keeper defines the precisebank module's keeper +type Keeper struct { + cdc codec.BinaryCodec + storeKey storetypes.StoreKey + + bk types.BankKeeper + ak types.AccountKeeper +} + +// NewKeeper creates a new keeper +func NewKeeper( + cdc codec.BinaryCodec, + storeKey storetypes.StoreKey, + bk types.BankKeeper, + ak types.AccountKeeper, +) Keeper { + return Keeper{ + cdc: cdc, + storeKey: storeKey, + bk: bk, + ak: ak, + } +} diff --git a/x/precisebank/keeper/keeper_test.go b/x/precisebank/keeper/keeper_test.go new file mode 100644 index 00000000..6bdadf0b --- /dev/null +++ b/x/precisebank/keeper/keeper_test.go @@ -0,0 +1,53 @@ +package keeper_test + +import ( + "testing" + + sdkmath "cosmossdk.io/math" + storetypes "github.com/cosmos/cosmos-sdk/store/types" + "github.com/cosmos/cosmos-sdk/testutil" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/precisebank/keeper" + "github.com/0glabs/0g-chain/x/precisebank/types" + "github.com/0glabs/0g-chain/x/precisebank/types/mocks" +) + +// testData defines necessary fields for testing keeper store methods and mocks +// for unit tests without full app setup. +type testData struct { + ctx sdk.Context + keeper keeper.Keeper + storeKey *storetypes.KVStoreKey + bk *mocks.MockBankKeeper + ak *mocks.MockAccountKeeper +} + +// NewMockedTestData creates a new testData instance with mocked bank and +// account keepers. +func NewMockedTestData(t *testing.T) testData { + storeKey := sdk.NewKVStoreKey(types.ModuleName) + // Not required by module, but needs to be non-nil for context + tKey := sdk.NewTransientStoreKey("transient_test") + ctx := testutil.DefaultContext(storeKey, tKey) + + bk := mocks.NewMockBankKeeper(t) + ak := mocks.NewMockAccountKeeper(t) + + tApp := app.NewTestApp() + cdc := tApp.AppCodec() + k := keeper.NewKeeper(cdc, storeKey, bk, ak) + + return testData{ + ctx: ctx, + keeper: k, + storeKey: storeKey, + bk: bk, + ak: ak, + } +} + +func c(denom string, amount int64) sdk.Coin { return sdk.NewInt64Coin(denom, amount) } +func ci(denom string, amount sdkmath.Int) sdk.Coin { return sdk.NewCoin(denom, amount) } +func cs(coins ...sdk.Coin) sdk.Coins { return sdk.NewCoins(coins...) } diff --git a/x/precisebank/keeper/mint.go b/x/precisebank/keeper/mint.go new file mode 100644 index 00000000..76c1d7c7 --- /dev/null +++ b/x/precisebank/keeper/mint.go @@ -0,0 +1,212 @@ +package keeper + +import ( + "fmt" + + errorsmod "cosmossdk.io/errors" + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + + "github.com/0glabs/0g-chain/x/precisebank/types" +) + +// MintCoins creates new coins from thin air and adds it to the module account. +// If ExtendedCoinDenom is provided, the corresponding fractional amount is +// added to the module state. +// It will panic if the module account does not exist or is unauthorized. +func (k Keeper) MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error { + // Disallow minting to x/precisebank module + if moduleName == types.ModuleName { + panic(errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "module account %s cannot be minted to", moduleName)) + } + + // Note: MintingRestrictionFn is not used in x/precisebank + // Panic errors are identical to x/bank for consistency. + acc := k.ak.GetModuleAccount(ctx, moduleName) + if acc == nil { + panic(errorsmod.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", moduleName)) + } + + if !acc.HasPermission(authtypes.Minter) { + panic(errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "module account %s does not have permissions to mint tokens", moduleName)) + } + + // Ensure the coins are valid before minting + if !amt.IsValid() { + return errorsmod.Wrap(sdkerrors.ErrInvalidCoins, amt.String()) + } + + // Get non-ExtendedCoinDenom coins + passthroughCoins := amt + + extendedAmount := amt.AmountOf(types.ExtendedCoinDenom) + if extendedAmount.IsPositive() { + // Remove ExtendedCoinDenom from the coins as it is managed by x/precisebank + removeCoin := sdk.NewCoin(types.ExtendedCoinDenom, extendedAmount) + passthroughCoins = amt.Sub(removeCoin) + } + + // Coins unmanaged by x/precisebank are passed through to x/bank + if !passthroughCoins.Empty() { + if err := k.bk.MintCoins(ctx, moduleName, passthroughCoins); err != nil { + return err + } + } + + // Only mint extended coin if the amount is positive + if extendedAmount.IsPositive() { + if err := k.mintExtendedCoin(ctx, moduleName, extendedAmount); err != nil { + return err + } + } + + fullEmissionCoins := sdk.NewCoins(types.SumExtendedCoin(amt)) + if fullEmissionCoins.IsZero() { + return nil + } + + ctx.EventManager().EmitEvents(sdk.Events{ + banktypes.NewCoinMintEvent(acc.GetAddress(), fullEmissionCoins), + banktypes.NewCoinReceivedEvent(acc.GetAddress(), fullEmissionCoins), + }) + + return nil +} + +// mintExtendedCoin manages the minting of only extended coins. This also +// handles integer carry over from fractional balance to integer balance if +// necessary depending on the fractional balance and minting amount. Ensures +// that the reserve fully backs the additional minted amount, minting any extra +// reserve integer coins if necessary. +// 4 Cases: +// 1. NO integer carry over, >= 0 remainder - no reserve mint +// 2. NO integer carry over, negative remainder - mint 1 to reserve +// 3. Integer carry over, >= 0 remainder +// - Transfer 1 integer from reserve -> account +// +// 4. Integer carry over, negative remainder +// - Transfer 1 integer from reserve -> account +// - Mint 1 to reserve +// Optimization: +// - Increase direct account mint amount by 1, no extra reserve mint +func (k Keeper) mintExtendedCoin( + ctx sdk.Context, + recipientModuleName string, + amt sdkmath.Int, +) error { + moduleAddr := k.ak.GetModuleAddress(recipientModuleName) + + // Get current module account fractional balance - 0 if not found + fractionalAmount := k.GetFractionalBalance(ctx, moduleAddr) + + // Get separated mint amounts + integerMintAmount := amt.Quo(types.ConversionFactor()) + fractionalMintAmount := amt.Mod(types.ConversionFactor()) + + // Get previous remainder amount, as we need to it before carry calculation + // for the optimization path. + prevRemainder := k.GetRemainderAmount(ctx) + + // Deduct new remainder with minted fractional amount. This will result in + // two cases: + // 1. Zero or positive remainder: remainder is sufficient to back the minted + // fractional amount. Reserve is also sufficient to back the minted amount + // so no additional reserve integer coin is needed. + // 2. Negative remainder: remainder is insufficient to back the minted + // fractional amount. Reserve will need to be increased to back the mint + // amount. + newRemainder := prevRemainder.Sub(fractionalMintAmount) + + // Get new fractional balance after minting, this could be greater than + // the conversion factor and must be checked for carry over to integer mint + // amount as being set as-is may cause fractional balance exceeding max. + newFractionalBalance := fractionalAmount.Add(fractionalMintAmount) + + // Case #3 - Integer carry, remainder is sufficient (0 or positive) + if newFractionalBalance.GTE(types.ConversionFactor()) && newRemainder.GTE(sdkmath.ZeroInt()) { + // Carry should send from reserve -> account, instead of minting an + // extra integer coin. Otherwise doing an extra mint will require a burn + // from reserves to maintain exact backing. + carryCoin := sdk.NewCoin(types.IntegerCoinDenom, sdkmath.OneInt()) + + // SendCoinsFromModuleToModule allows for sending coins even if the + // recipient module account is blocked. + if err := k.bk.SendCoinsFromModuleToModule( + ctx, + types.ModuleName, + recipientModuleName, + sdk.NewCoins(carryCoin), + ); err != nil { + return err + } + } + + // Case #4 - Integer carry, remainder is insufficient + // This is the optimization path where the integer mint amount is increased + // by 1, instead of doing both a reserve -> account transfer and reserve mint. + if newFractionalBalance.GTE(types.ConversionFactor()) && newRemainder.IsNegative() { + integerMintAmount = integerMintAmount.AddRaw(1) + } + + // If it carries over, adjust the fractional balance to account for the + // previously added 1 integer amount. + // fractional amounts x and y where both x and y < ConversionFactor + // x + y < (2 * ConversionFactor) - 2 + // x + y < 1 integer amount + fractional amount + if newFractionalBalance.GTE(types.ConversionFactor()) { + // Subtract 1 integer equivalent amount of fractional balance. Same + // behavior as using .Mod() in this case. + newFractionalBalance = newFractionalBalance.Sub(types.ConversionFactor()) + } + + // Mint new integer amounts in x/bank - including carry over from fractional + // amount if any. + if integerMintAmount.IsPositive() { + integerMintCoin := sdk.NewCoin(types.IntegerCoinDenom, integerMintAmount) + + if err := k.bk.MintCoins( + ctx, + recipientModuleName, + sdk.NewCoins(integerMintCoin), + ); err != nil { + return err + } + } + + // Assign new fractional balance in x/precisebank + k.SetFractionalBalance(ctx, moduleAddr, newFractionalBalance) + + // ---------------------------------------- + // Update remainder & reserves to back minted fractional coins + + // Mint an additional reserve integer coin if remainder is insufficient. + // The remainder is the amount of fractional coins that can be minted and + // still be fully backed by reserve. If the remainder is less than the + // minted fractional amount, then the reserve needs to be increased to + // back the additional fractional amount. + // Optimization: This is only done when the integer amount does NOT carry, + // as a direct account mint is done instead of integer carry transfer + + // insufficient remainder reserve mint. + wasCarried := fractionalAmount.Add(fractionalMintAmount).GTE(types.ConversionFactor()) + if prevRemainder.LT(fractionalMintAmount) && !wasCarried { + // Always only 1 integer coin, as fractionalMintAmount < ConversionFactor + reserveMintCoins := sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdkmath.OneInt())) + if err := k.bk.MintCoins(ctx, types.ModuleName, reserveMintCoins); err != nil { + return fmt.Errorf("failed to mint %s for reserve: %w", reserveMintCoins, err) + } + } + + // newRemainder will be negative if prevRemainder < fractionalMintAmount. + // This needs to be adjusted back to the corresponding positive value. The + // remainder will be always < conversionFactor after add if it is negative. + if newRemainder.IsNegative() { + newRemainder = newRemainder.Add(types.ConversionFactor()) + } + + k.SetRemainderAmount(ctx, newRemainder) + + return nil +} diff --git a/x/precisebank/keeper/mint_integration_test.go b/x/precisebank/keeper/mint_integration_test.go new file mode 100644 index 00000000..67880138 --- /dev/null +++ b/x/precisebank/keeper/mint_integration_test.go @@ -0,0 +1,424 @@ +package keeper_test + +import ( + "fmt" + "testing" + + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + + "github.com/0glabs/0g-chain/x/precisebank/keeper" + "github.com/0glabs/0g-chain/x/precisebank/testutil" + "github.com/0glabs/0g-chain/x/precisebank/types" + "github.com/stretchr/testify/suite" +) + +type mintIntegrationTestSuite struct { + testutil.Suite +} + +func (suite *mintIntegrationTestSuite) SetupTest() { + suite.Suite.SetupTest() +} + +func TestMintIntegrationTest(t *testing.T) { + suite.Run(t, new(mintIntegrationTestSuite)) +} + +func (suite *mintIntegrationTestSuite) TestBlockedRecipient() { + // Tests that sending funds to x/precisebank is disallowed. + // x/precisebank balance is used as the reserve funds and should not be + // directly interacted with by external modules or users. + msgServer := bankkeeper.NewMsgServerImpl(suite.BankKeeper) + + fromAddr := sdk.AccAddress{1} + + // To x/precisebank + toAddr := suite.AccountKeeper.GetModuleAddress(types.ModuleName) + amount := cs(c("ukava", 1000)) + + msg := banktypes.NewMsgSend(fromAddr, toAddr, amount) + + _, err := msgServer.Send(sdk.WrapSDKContext(suite.Ctx), msg) + suite.Require().Error(err) + + suite.Require().EqualError( + err, + fmt.Sprintf("%s is not allowed to receive funds: unauthorized", toAddr.String()), + ) +} + +func (suite *mintIntegrationTestSuite) TestMintCoins_MatchingErrors() { + // x/precisebank MintCoins should be identical to x/bank MintCoins to + // consumers. This test ensures that the panics & errors returned by + // x/precisebank are identical to x/bank. + + tests := []struct { + name string + recipientModule string + mintAmount sdk.Coins + wantErr string + wantPanic string + }{ + { + "invalid module", + "notamodule", + cs(c("ukava", 1000)), + "", + "module account notamodule does not exist: unknown address", + }, + { + "no mint permissions", + // Check app.go to ensure this module has no mint permissions + authtypes.FeeCollectorName, + cs(c("ukava", 1000)), + "", + "module account fee_collector does not have permissions to mint tokens: unauthorized", + }, + { + "invalid amount", + minttypes.ModuleName, + sdk.Coins{sdk.Coin{Denom: "ukava", Amount: sdkmath.NewInt(-100)}}, + "-100ukava: invalid coins", + "", + }, + } + + for _, tt := range tests { + suite.Run(tt.name, func() { + // Reset + suite.SetupTest() + + if tt.wantErr == "" && tt.wantPanic == "" { + suite.Fail("test must specify either wantErr or wantPanic") + } + + if tt.wantErr != "" { + // Check x/bank MintCoins for identical error + bankErr := suite.BankKeeper.MintCoins(suite.Ctx, tt.recipientModule, tt.mintAmount) + suite.Require().Error(bankErr) + suite.Require().EqualError(bankErr, tt.wantErr, "expected error should match x/bank MintCoins error") + + pbankErr := suite.Keeper.MintCoins(suite.Ctx, tt.recipientModule, tt.mintAmount) + suite.Require().Error(pbankErr) + // Compare strings instead of errors, as error stack is still different + suite.Require().Equal( + bankErr.Error(), + pbankErr.Error(), + "x/precisebank error should match x/bank MintCoins error", + ) + } + + if tt.wantPanic != "" { + // First check the wantPanic string is correct. + // Actually specify the panic string in the test since it makes + // it more clear we are testing specific and different cases. + suite.Require().PanicsWithError(tt.wantPanic, func() { + _ = suite.BankKeeper.MintCoins(suite.Ctx, tt.recipientModule, tt.mintAmount) + }, "expected panic error should match x/bank MintCoins") + + suite.Require().PanicsWithError(tt.wantPanic, func() { + _ = suite.Keeper.MintCoins(suite.Ctx, tt.recipientModule, tt.mintAmount) + }, "x/precisebank panic should match x/bank MintCoins") + } + }) + } +} + +func (suite *mintIntegrationTestSuite) TestMintCoins() { + type mintTest struct { + mintAmount sdk.Coins + // Expected **full** balances after MintCoins(mintAmount) + wantBalance sdk.Coins + } + + tests := []struct { + name string + recipientModule string + // Instead of having a start balance, we just have a list of mints to + // both test & get into desired non-default states. + mints []mintTest + }{ + { + "passthrough - unrelated", + minttypes.ModuleName, + []mintTest{ + { + mintAmount: cs(c("busd", 1000)), + wantBalance: cs(c("busd", 1000)), + }, + }, + }, + { + "passthrough - integer denom", + minttypes.ModuleName, + []mintTest{ + { + mintAmount: cs(c(types.IntegerCoinDenom, 1000)), + wantBalance: cs(c(types.ExtendedCoinDenom, 1000000000000000)), + }, + }, + }, + { + "fractional only", + minttypes.ModuleName, + []mintTest{ + { + mintAmount: cs(c(types.ExtendedCoinDenom, 1000)), + wantBalance: cs(c(types.ExtendedCoinDenom, 1000)), + }, + { + mintAmount: cs(c(types.ExtendedCoinDenom, 1000)), + wantBalance: cs(c(types.ExtendedCoinDenom, 2000)), + }, + }, + }, + { + "fractional only with carry", + minttypes.ModuleName, + []mintTest{ + { + // Start with (1/4 * 3) = 0.75 + mintAmount: cs(ci(types.ExtendedCoinDenom, types.ConversionFactor().QuoRaw(4).MulRaw(3))), + wantBalance: cs(ci(types.ExtendedCoinDenom, types.ConversionFactor().QuoRaw(4).MulRaw(3))), + }, + { + // Add another 0.50 to incur carry to test reserve on carry + mintAmount: cs(ci(types.ExtendedCoinDenom, types.ConversionFactor().QuoRaw(2))), + wantBalance: cs(ci(types.ExtendedCoinDenom, types.ConversionFactor().QuoRaw(4).MulRaw(5))), + }, + }, + }, + { + "fractional only, resulting in exact carry and 0 remainder", + minttypes.ModuleName, + []mintTest{ + // mint 0.5, acc = 0.5, reserve = 1 + { + mintAmount: cs(ci(types.ExtendedCoinDenom, types.ConversionFactor().QuoRaw(2))), + wantBalance: cs(ci(types.ExtendedCoinDenom, types.ConversionFactor().QuoRaw(2))), + }, + // mint another 0.5, acc = 1, reserve = 0 + // Reserve actually goes down by 1 for integer carry + { + mintAmount: cs(ci(types.ExtendedCoinDenom, types.ConversionFactor().QuoRaw(2))), + wantBalance: cs(ci(types.ExtendedCoinDenom, types.ConversionFactor())), + }, + }, + }, + { + "exact carry", + minttypes.ModuleName, + []mintTest{ + { + mintAmount: cs(ci(types.ExtendedCoinDenom, types.ConversionFactor())), + wantBalance: cs(ci(types.ExtendedCoinDenom, types.ConversionFactor())), + }, + // Carry again - exact amount + { + mintAmount: cs(ci(types.ExtendedCoinDenom, types.ConversionFactor())), + wantBalance: cs(ci(types.ExtendedCoinDenom, types.ConversionFactor().MulRaw(2))), + }, + }, + }, + { + "carry with extra", + minttypes.ModuleName, + []mintTest{ + // MintCoins(C + 100) + { + mintAmount: cs(ci(types.ExtendedCoinDenom, types.ConversionFactor().AddRaw(100))), + wantBalance: cs(ci(types.ExtendedCoinDenom, types.ConversionFactor().AddRaw(100))), + }, + // MintCoins(C + 5), total = 2C + 105 + { + mintAmount: cs(ci(types.ExtendedCoinDenom, types.ConversionFactor().AddRaw(5))), + wantBalance: cs(ci(types.ExtendedCoinDenom, types.ConversionFactor().MulRaw(2).AddRaw(105))), + }, + }, + }, + { + "integer with fractional", + minttypes.ModuleName, + []mintTest{ + { + mintAmount: cs(ci(types.ExtendedCoinDenom, types.ConversionFactor().MulRaw(5).AddRaw(100))), + wantBalance: cs(ci(types.ExtendedCoinDenom, types.ConversionFactor().MulRaw(5).AddRaw(100))), + }, + { + mintAmount: cs(ci(types.ExtendedCoinDenom, types.ConversionFactor().MulRaw(2).AddRaw(5))), + wantBalance: cs(ci(types.ExtendedCoinDenom, types.ConversionFactor().MulRaw(7).AddRaw(105))), + }, + }, + }, + { + "with passthrough", + minttypes.ModuleName, + []mintTest{ + { + mintAmount: cs( + ci(types.ExtendedCoinDenom, types.ConversionFactor().MulRaw(5).AddRaw(100)), + c("busd", 1000), + ), + wantBalance: cs( + ci(types.ExtendedCoinDenom, types.ConversionFactor().MulRaw(5).AddRaw(100)), + c("busd", 1000), + ), + }, + { + mintAmount: cs( + ci(types.ExtendedCoinDenom, types.ConversionFactor().MulRaw(2).AddRaw(5)), + c("meow", 40), + ), + wantBalance: cs( + ci(types.ExtendedCoinDenom, types.ConversionFactor().MulRaw(7).AddRaw(105)), + c("busd", 1000), + c("meow", 40), + ), + }, + }, + }, + } + + for _, tt := range tests { + suite.Run(tt.name, func() { + // Reset + suite.SetupTest() + + recipientAddr := suite.AccountKeeper.GetModuleAddress(tt.recipientModule) + + for _, mt := range tt.mints { + err := suite.Keeper.MintCoins(suite.Ctx, tt.recipientModule, mt.mintAmount) + suite.Require().NoError(err) + + // ------------------------------------------------------------- + // Check FULL balances + // x/bank balances + x/precisebank balance + // Exclude "ukava" as x/precisebank balance will include it + bankCoins := suite.BankKeeper.GetAllBalances(suite.Ctx, recipientAddr) + + // Only use x/bank balances for non-ukava denoms + var denoms []string + for _, coin := range bankCoins { + // Ignore integer coins, query the extended denom instead + if coin.Denom == types.IntegerCoinDenom { + continue + } + + denoms = append(denoms, coin.Denom) + } + + // Add the extended denom to the list of denoms to balance check + // Will be included in balance check even if x/bank doesn't have + // ukava. + denoms = append(denoms, types.ExtendedCoinDenom) + + // All balance queries through x/precisebank + afterBalance := sdk.NewCoins() + for _, denom := range denoms { + coin := suite.Keeper.GetBalance(suite.Ctx, recipientAddr, denom) + afterBalance = afterBalance.Add(coin) + } + + suite.Require().Equal( + mt.wantBalance.String(), + afterBalance.String(), + "unexpected balance after minting %s to %s", + ) + + // Ensure reserve is backing all minted fractions + allInvariantsFn := keeper.AllInvariants(suite.Keeper) + msg, stop := allInvariantsFn(suite.Ctx) + suite.Require().Falsef(stop, "invariant should not be broken: %s", msg) + + // Get event for minted coins + intCoinAmt := mt.mintAmount.AmountOf(types.IntegerCoinDenom). + Mul(types.ConversionFactor()) + + fraCoinAmt := mt.mintAmount.AmountOf(types.ExtendedCoinDenom) + + totalExtCoinAmt := intCoinAmt.Add(fraCoinAmt) + extCoins := sdk.NewCoins(sdk.NewCoin(types.ExtendedCoinDenom, totalExtCoinAmt)) + + // Check for mint event + events := suite.Ctx.EventManager().Events() + + expMintEvent := banktypes.NewCoinMintEvent( + recipientAddr, + extCoins, + ) + + expReceivedEvent := banktypes.NewCoinReceivedEvent( + recipientAddr, + extCoins, + ) + + if totalExtCoinAmt.IsZero() { + suite.Require().NotContains(events, expMintEvent) + suite.Require().NotContains(events, expReceivedEvent) + } else { + suite.Require().Contains(events, expMintEvent) + suite.Require().Contains(events, expReceivedEvent) + } + } + }) + } +} + +func FuzzMintCoins(f *testing.F) { + f.Add(int64(0)) + f.Add(int64(100)) + f.Add(types.ConversionFactor().Int64()) + f.Add(types.ConversionFactor().QuoRaw(2).Int64()) + f.Add(types.ConversionFactor().MulRaw(5).Int64()) + f.Add(types.ConversionFactor().MulRaw(2).AddRaw(123948723).Int64()) + + f.Fuzz(func(t *testing.T, amount int64) { + // No negative amounts + if amount < 0 { + amount = -amount + } + + // Manually setup test suite since no direct Fuzz support in test suites + suite := new(mintIntegrationTestSuite) + suite.SetT(t) + suite.SetS(suite) + suite.SetupTest() + + mintCount := int64(10) + + suite.T().Logf("minting %d %d times", amount, mintCount) + + // Mint 10 times to include mints from non-zero balances + for i := int64(0); i < mintCount; i++ { + err := suite.Keeper.MintCoins( + suite.Ctx, + minttypes.ModuleName, + cs(c(types.ExtendedCoinDenom, amount)), + ) + suite.Require().NoError(err) + } + + // Check FULL balances + recipientAddr := suite.AccountKeeper.GetModuleAddress(minttypes.ModuleName) + bal := suite.Keeper.GetBalance(suite.Ctx, recipientAddr, types.ExtendedCoinDenom) + + suite.Require().Equalf( + amount*mintCount, + bal.Amount.Int64(), + "unexpected balance after minting %d %d times", + amount, + mintCount, + ) + + // Run Invariants to ensure remainder is backing all minted fractions + // and in a valid state + res, stop := keeper.AllInvariants(suite.Keeper)(suite.Ctx) + suite.False(stop, "invariant should not be broken") + suite.Empty(res, "unexpected invariant message") + }) +} diff --git a/x/precisebank/keeper/mint_test.go b/x/precisebank/keeper/mint_test.go new file mode 100644 index 00000000..d2619d83 --- /dev/null +++ b/x/precisebank/keeper/mint_test.go @@ -0,0 +1,366 @@ +package keeper_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + + "github.com/0glabs/0g-chain/x/precisebank/types" +) + +func TestMintCoins_PanicValidations(t *testing.T) { + // panic tests for invalid inputs + + tests := []struct { + name string + recipientModule string + setupFn func(td testData) + mintAmount sdk.Coins + wantPanic string + }{ + { + "invalid module", + "notamodule", + func(td testData) { + // Make module not found + td.ak.EXPECT(). + GetModuleAccount(td.ctx, "notamodule"). + Return(nil). + Once() + }, + cs(c("ukava", 1000)), + "module account notamodule does not exist: unknown address", + }, + { + "no permission", + minttypes.ModuleName, + func(td testData) { + td.ak.EXPECT(). + GetModuleAccount(td.ctx, minttypes.ModuleName). + Return(authtypes.NewModuleAccount( + authtypes.NewBaseAccountWithAddress(sdk.AccAddress{1}), + minttypes.ModuleName, + // no mint permission + )). + Once() + }, + cs(c("ukava", 1000)), + "module account mint does not have permissions to mint tokens: unauthorized", + }, + { + "has mint permission", + minttypes.ModuleName, + func(td testData) { + td.ak.EXPECT(). + GetModuleAccount(td.ctx, minttypes.ModuleName). + Return(authtypes.NewModuleAccount( + authtypes.NewBaseAccountWithAddress(sdk.AccAddress{1}), + minttypes.ModuleName, + // includes minter permission + authtypes.Minter, + )). + Once() + + // Will call x/bank MintCoins coins + td.bk.EXPECT(). + MintCoins(td.ctx, minttypes.ModuleName, cs(c("ukava", 1000))). + Return(nil). + Once() + }, + cs(c("ukava", 1000)), + "", + }, + { + "disallow minting to x/precisebank", + types.ModuleName, + func(td testData) { + // No mock setup needed since this is checked before module + // account checks + }, + cs(c("ukava", 1000)), + "module account precisebank cannot be minted to: unauthorized", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + td := NewMockedTestData(t) + tt.setupFn(td) + + if tt.wantPanic != "" { + require.PanicsWithError(t, tt.wantPanic, func() { + _ = td.keeper.MintCoins(td.ctx, tt.recipientModule, tt.mintAmount) + }) + return + } + + require.NotPanics(t, func() { + // Not testing errors, only panics for this test + _ = td.keeper.MintCoins(td.ctx, tt.recipientModule, tt.mintAmount) + }) + }) + } +} + +func TestMintCoins_Errors(t *testing.T) { + // returned errors, not panics + + tests := []struct { + name string + recipientModule string + setupFn func(td testData) + mintAmount sdk.Coins + wantError string + }{ + { + "invalid coins", + minttypes.ModuleName, + func(td testData) { + // Valid module account minter + td.ak.EXPECT(). + GetModuleAccount(td.ctx, minttypes.ModuleName). + Return(authtypes.NewModuleAccount( + authtypes.NewBaseAccountWithAddress(sdk.AccAddress{1}), + minttypes.ModuleName, + // includes minter permission + authtypes.Minter, + )). + Once() + }, + sdk.Coins{sdk.Coin{ + Denom: "ukava", + Amount: sdk.NewInt(-1000), + }}, + "-1000ukava: invalid coins", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + td := NewMockedTestData(t) + tt.setupFn(td) + + require.NotPanics(t, func() { + err := td.keeper.MintCoins(td.ctx, tt.recipientModule, tt.mintAmount) + + if tt.wantError != "" { + require.Error(t, err) + require.EqualError(t, err, tt.wantError) + return + } + + require.NoError(t, err) + }) + }) + } +} + +func TestMintCoins_ExpectedCalls(t *testing.T) { + // Tests the expected calls to the bank keeper when minting coins + + tests := []struct { + name string + // Only care about starting fractional balance. + // MintCoins() doesn't care about the previous integer balance. + startFractionalBalance sdkmath.Int + mintAmount sdk.Coins + // account x/precisebank balance (fractional amount) + wantPreciseBalance sdkmath.Int + }{ + { + "passthrough mint - integer denom", + sdkmath.ZeroInt(), + cs(c("ukava", 1000)), + sdkmath.ZeroInt(), + }, + + { + "passthrough mint - unrelated denom", + sdkmath.ZeroInt(), + cs(c("meow", 1000)), + sdkmath.ZeroInt(), + }, + { + "no carry - 0 starting fractional", + sdkmath.ZeroInt(), + cs(c(types.ExtendedCoinDenom, 1000)), + sdkmath.NewInt(1000), + }, + { + "no carry - non-zero fractional", + sdkmath.NewInt(1_000_000), + cs(c(types.ExtendedCoinDenom, 1000)), + sdkmath.NewInt(1_001_000), + }, + { + "fractional carry", + // max fractional amount + types.ConversionFactor().SubRaw(1), + cs(c(types.ExtendedCoinDenom, 1)), // +1 to carry + sdkmath.ZeroInt(), + }, + { + "fractional carry max", + // max fractional amount + max fractional amount + types.ConversionFactor().SubRaw(1), + cs(ci(types.ExtendedCoinDenom, types.ConversionFactor().SubRaw(1))), + types.ConversionFactor().SubRaw(2), + }, + { + "integer with fractional no carry", + sdkmath.NewInt(1234), + // mint 100 fractional + cs(c(types.ExtendedCoinDenom, 100)), + sdkmath.NewInt(1234 + 100), + }, + { + "integer with fractional carry", + types.ConversionFactor().SubRaw(100), + // mint 105 fractional to carry + cs(c(types.ExtendedCoinDenom, 105)), + sdkmath.NewInt(5), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + td := NewMockedTestData(t) + + // Set initial fractional balance + // Initial integer balance doesn't matter for this test + moduleAddr := sdk.AccAddress{1} + td.keeper.SetFractionalBalance( + td.ctx, + moduleAddr, + tt.startFractionalBalance, + ) + fBal := td.keeper.GetFractionalBalance(td.ctx, moduleAddr) + require.Equal(t, tt.startFractionalBalance, fBal) + + // Always calls GetModuleAccount() to check if module exists & + // has permission + td.ak.EXPECT(). + GetModuleAccount(td.ctx, minttypes.ModuleName). + Return(authtypes.NewModuleAccount( + authtypes.NewBaseAccountWithAddress( + moduleAddr, + ), + minttypes.ModuleName, + // Include minter permissions - not testing permission in + // this test + authtypes.Minter, + )). + Once() + + // ---------------------------------------- + // Separate passthrough and extended coins + // Determine how much is passed through to x/bank + passthroughCoins := tt.mintAmount + + found, extCoins := tt.mintAmount.Find(types.ExtendedCoinDenom) + if found { + // Remove extended coin from passthrough coins + passthroughCoins = passthroughCoins.Sub(extCoins) + } else { + extCoins = sdk.NewCoin(types.ExtendedCoinDenom, sdkmath.ZeroInt()) + } + + require.Equalf( + t, + sdkmath.ZeroInt(), + passthroughCoins.AmountOf(types.ExtendedCoinDenom), + "expected pass through coins should not include %v", + types.ExtendedCoinDenom, + ) + + // ---------------------------------------- + // Set expectations for minting passthrough coins + // Only expect MintCoins to be called with passthrough coins with non-zero amount + if !passthroughCoins.Empty() { + t.Logf("Expecting MintCoins(%v)", passthroughCoins) + + td.bk.EXPECT(). + MintCoins(td.ctx, minttypes.ModuleName, passthroughCoins). + Return(nil). + Once() + } + + // ---------------------------------------- + // Set expectations for reserve minting when fractional amounts + // are minted & remainder is insufficient + mintFractionalAmount := extCoins.Amount.Mod(types.ConversionFactor()) + currentRemainder := td.keeper.GetRemainderAmount(td.ctx) + + causesIntegerCarry := fBal.Add(mintFractionalAmount).GTE(types.ConversionFactor()) + remainderEnough := currentRemainder.GTE(mintFractionalAmount) + + // Optimization: Carry & insufficient remainder is directly minted + if causesIntegerCarry && !remainderEnough { + extCoins = extCoins.AddAmount(types.ConversionFactor()) + } + + // ---------------------------------------- + // Set expectations for minting fractional coins + if !extCoins.IsNil() && extCoins.IsPositive() { + td.ak.EXPECT(). + GetModuleAddress(minttypes.ModuleName). + Return(moduleAddr). + Once() + + // Initial integer balance is always 0 for this test + mintIntegerAmount := extCoins.Amount.Quo(types.ConversionFactor()) + + // Minted coins does NOT include roll-over, simply excludes + mintCoins := cs(ci(types.IntegerCoinDenom, mintIntegerAmount)) + + // Only expect MintCoins to be called with mint coins with + // non-zero amount. + // Will fail if x/bank MintCoins is called with empty coins + if !mintCoins.Empty() { + t.Logf("Expecting MintCoins(%v)", mintCoins) + + td.bk.EXPECT(). + MintCoins(td.ctx, minttypes.ModuleName, mintCoins). + Return(nil). + Once() + } + } + + if causesIntegerCarry && remainderEnough { + td.bk.EXPECT(). + SendCoinsFromModuleToModule( + td.ctx, + types.ModuleName, + minttypes.ModuleName, + cs(c(types.IntegerCoinDenom, 1)), + ). + Return(nil). + Once() + } + + if !remainderEnough && !causesIntegerCarry { + reserveMintCoins := cs(c(types.IntegerCoinDenom, 1)) + td.bk.EXPECT(). + // Mints to x/precisebank + MintCoins(td.ctx, types.ModuleName, reserveMintCoins). + Return(nil). + Once() + } + + // ---------------------------------------- + // Actual call after all setup and expectations + require.NotPanics(t, func() { + err := td.keeper.MintCoins(td.ctx, minttypes.ModuleName, tt.mintAmount) + require.NoError(t, err) + }) + + // Check final fractional balance + fBal = td.keeper.GetFractionalBalance(td.ctx, moduleAddr) + require.Equal(t, tt.wantPreciseBalance, fBal) + }) + } +} diff --git a/x/precisebank/keeper/remainder_amount.go b/x/precisebank/keeper/remainder_amount.go new file mode 100644 index 00000000..32ae2fdf --- /dev/null +++ b/x/precisebank/keeper/remainder_amount.go @@ -0,0 +1,66 @@ +package keeper + +import ( + "fmt" + + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/x/precisebank/types" +) + +// GetRemainderAmount returns the internal remainder amount. +func (k *Keeper) GetRemainderAmount( + ctx sdk.Context, +) sdkmath.Int { + store := ctx.KVStore(k.storeKey) + + bz := store.Get(types.RemainderBalanceKey) + if bz == nil { + return sdkmath.ZeroInt() + } + + var bal sdkmath.Int + if err := bal.Unmarshal(bz); err != nil { + panic(fmt.Errorf("failed to unmarshal remainder amount: %w", err)) + } + + return bal +} + +// SetRemainderAmount sets the internal remainder amount. +func (k *Keeper) SetRemainderAmount( + ctx sdk.Context, + amount sdkmath.Int, +) { + // Prevent storing zero amounts. In practice, the remainder amount should + // only be non-zero during transactions as mint and burns should net zero + // due to only being used for EVM transfers. + if amount.IsZero() { + k.DeleteRemainderAmount(ctx) + return + } + + // Ensure the remainder is valid before setting it. Follows the same + // validation as FractionalBalance with the same value range. + if err := types.ValidateFractionalAmount(amount); err != nil { + panic(fmt.Errorf("remainder amount is invalid: %w", err)) + } + + store := ctx.KVStore(k.storeKey) + + amountBytes, err := amount.Marshal() + if err != nil { + panic(fmt.Errorf("failed to marshal remainder amount: %w", err)) + } + + store.Set(types.RemainderBalanceKey, amountBytes) +} + +// DeleteRemainderAmount deletes the internal remainder amount. +func (k *Keeper) DeleteRemainderAmount( + ctx sdk.Context, +) { + store := ctx.KVStore(k.storeKey) + store.Delete(types.RemainderBalanceKey) +} diff --git a/x/precisebank/keeper/remainder_amount_test.go b/x/precisebank/keeper/remainder_amount_test.go new file mode 100644 index 00000000..ca2969f6 --- /dev/null +++ b/x/precisebank/keeper/remainder_amount_test.go @@ -0,0 +1,71 @@ +package keeper_test + +import ( + "testing" + + sdkmath "cosmossdk.io/math" + "github.com/0glabs/0g-chain/x/precisebank/types" + "github.com/stretchr/testify/require" +) + +func TestGetSetRemainderAmount(t *testing.T) { + tk := NewMockedTestData(t) + ctx, k, storeKey := tk.ctx, tk.keeper, tk.storeKey + + // Set amount + k.SetRemainderAmount(ctx, sdkmath.NewInt(100)) + + amt := k.GetRemainderAmount(ctx) + require.Equal(t, sdkmath.NewInt(100), amt) + + // Set zero balance + k.SetRemainderAmount(ctx, sdkmath.ZeroInt()) + + amt = k.GetRemainderAmount(ctx) + require.Equal(t, sdkmath.ZeroInt(), amt) + + // Get directly from store to make sure it was actually deleted + store := ctx.KVStore(storeKey) + bz := store.Get(types.RemainderBalanceKey) + require.Nil(t, bz) +} + +func TestInvalidRemainderAmount(t *testing.T) { + tk := NewMockedTestData(t) + ctx, k := tk.ctx, tk.keeper + + // Set negative amount + require.PanicsWithError(t, "remainder amount is invalid: non-positive amount -1", func() { + k.SetRemainderAmount(ctx, sdkmath.NewInt(-1)) + }) + + // Set amount over max + require.PanicsWithError(t, "remainder amount is invalid: amount 1000000000000 exceeds max of 999999999999", func() { + k.SetRemainderAmount(ctx, types.ConversionFactor()) + }) +} + +func TestDeleteRemainderAmount(t *testing.T) { + tk := NewMockedTestData(t) + ctx, k, storeKey := tk.ctx, tk.keeper, tk.storeKey + + require.NotPanics(t, func() { + k.DeleteRemainderAmount(ctx) + }) + + // Set amount + k.SetRemainderAmount(ctx, sdkmath.NewInt(100)) + + amt := k.GetRemainderAmount(ctx) + require.Equal(t, sdkmath.NewInt(100), amt) + + // Delete amount + k.DeleteRemainderAmount(ctx) + + amt = k.GetRemainderAmount(ctx) + require.Equal(t, sdkmath.ZeroInt(), amt) + + store := ctx.KVStore(storeKey) + bz := store.Get(types.RemainderBalanceKey) + require.Nil(t, bz) +} diff --git a/x/precisebank/keeper/send.go b/x/precisebank/keeper/send.go new file mode 100644 index 00000000..ce01cc61 --- /dev/null +++ b/x/precisebank/keeper/send.go @@ -0,0 +1,363 @@ +package keeper + +import ( + "errors" + "fmt" + + errorsmod "cosmossdk.io/errors" + sdkmath "cosmossdk.io/math" + "github.com/0glabs/0g-chain/x/precisebank/types" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +// IsSendEnabledCoins uses the parent x/bank keeper to check the coins provided +// and returns an ErrSendDisabled if any of the coins are not configured for +// sending. Returns nil if sending is enabled for all provided coin. +// Note: This method is not used directly by x/evm, but is still required as +// part of authtypes.BankKeeper. x/evm uses auth methods that require this +// interface. +func (k Keeper) IsSendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error { + // Simply pass through to x/bank + return k.bk.IsSendEnabledCoins(ctx, coins...) +} + +// SendCoins transfers amt coins from a sending account to a receiving account. +// An error is returned upon failure. This handles transfers including +// ExtendedCoinDenom and supports non-ExtendedCoinDenom transfers by passing +// through to x/bank. +func (k Keeper) SendCoins( + ctx sdk.Context, + from, to sdk.AccAddress, + amt sdk.Coins, +) error { + // IsSendEnabledCoins() is only used in x/bank in msg server, not in keeper, + // so we should also not use it here to align with x/bank behavior. + + if !amt.IsValid() { + return errorsmod.Wrap(sdkerrors.ErrInvalidCoins, amt.String()) + } + + passthroughCoins := amt + extendedCoinAmount := amt.AmountOf(types.ExtendedCoinDenom) + + // Remove the extended coin amount from the passthrough coins + if extendedCoinAmount.IsPositive() { + subCoin := sdk.NewCoin(types.ExtendedCoinDenom, extendedCoinAmount) + passthroughCoins = amt.Sub(subCoin) + } + + // Send the passthrough coins through x/bank + if passthroughCoins.IsAllPositive() { + if err := k.bk.SendCoins(ctx, from, to, passthroughCoins); err != nil { + return err + } + } + + // Send the extended coin amount through x/precisebank + if extendedCoinAmount.IsPositive() { + if err := k.sendExtendedCoins(ctx, from, to, extendedCoinAmount); err != nil { + return err + } + } + + // Get a full extended coin amount (passthrough integer + fractional) ONLY + // for event attributes. + fullEmissionCoins := sdk.NewCoins(types.SumExtendedCoin(amt)) + + // If no passthrough integer nor fractional coins, then no event emission. + // We also want to emit the event with the whole equivalent extended coin + // if only integer coins are sent. + if fullEmissionCoins.IsZero() { + return nil + } + + // Emit transfer event of extended denom for the FULL equivalent value. + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + banktypes.EventTypeTransfer, + sdk.NewAttribute(banktypes.AttributeKeyRecipient, to.String()), + sdk.NewAttribute(banktypes.AttributeKeySender, from.String()), + sdk.NewAttribute(sdk.AttributeKeyAmount, fullEmissionCoins.String()), + ), + banktypes.NewCoinSpentEvent(from, fullEmissionCoins), + banktypes.NewCoinReceivedEvent(to, fullEmissionCoins), + }) + + return nil +} + +// sendExtendedCoins transfers amt extended coins from a sending account to a +// receiving account. An error is returned upon failure. This function is +// called by SendCoins() and should not be called directly. +// +// This method covers 4 cases between two accounts - sender and receiver. +// Depending on the fractional balance and the amount being transferred: +// Sender account: +// 1. Arithmetic borrow 1 integer equivalent amount of fractional coins if the +// fractional balance is insufficient. +// 2. No borrow if fractional balance is sufficient. +// +// Receiver account: +// 1. Arithmetic carry 1 integer equivalent amount of fractional coins if the +// received amount exceeds max fractional balance. +// 2. No carry if received amount does not exceed max fractional balance. +// +// The 4 cases are: +// 1. Sender borrow, receiver carry +// 2. Sender borrow, NO receiver carry +// 3. NO sender borrow, receiver carry +// 4. NO sender borrow, NO receiver carry +// +// Truth table: +// | Sender Borrow | Receiver Carry | Direct Transfer | +// | --------------|----------------|-----------------| +// | T | T | T | +// | T | F | F | +// | F | T | F | +// | F | F | F | +func (k Keeper) sendExtendedCoins( + ctx sdk.Context, + from, to sdk.AccAddress, + amt sdkmath.Int, +) error { + // Sufficient balance check is done by bankkeeper.SendCoins(), for both + // integer and fractional-only sends. E.g. If fractional balance is + // insufficient, it will still incur a integer borrow which will fail if the + // sender does not have sufficient integer balance. + + // Load required state: Account old balances + senderFracBal := k.GetFractionalBalance(ctx, from) + recipientFracBal := k.GetFractionalBalance(ctx, to) + + // ------------------------------------------------------------------------- + // Pure stateless calculations + integerAmt := amt.Quo(types.ConversionFactor()) + fractionalAmt := amt.Mod(types.ConversionFactor()) + + // Account new fractional balances + senderNewFracBal, senderNeedsBorrow := subFromFractionalBalance(senderFracBal, fractionalAmt) + recipientNewFracBal, recipientNeedsCarry := addToFractionalBalance(recipientFracBal, fractionalAmt) + + // Case #1: Sender borrow, recipient carry + if senderNeedsBorrow && recipientNeedsCarry { + // Can directly transfer borrow/carry - increase the direct transfer by 1 + integerAmt = integerAmt.AddRaw(1) + } + + // ------------------------------------------------------------------------- + // Stateful operations for transfers + + // This includes ALL transfers of >= conversionFactor AND Case #1 + // Full integer amount transfer, including direct transfer of borrow/carry + // if any. + if integerAmt.IsPositive() { + transferCoin := sdk.NewCoin(types.IntegerCoinDenom, integerAmt) + if err := k.bk.SendCoins(ctx, from, to, sdk.NewCoins(transferCoin)); err != nil { + return k.updateInsufficientFundsError(ctx, from, amt, err) + } + } + + // Case #2: Sender borrow, NO recipient carry + // Sender borrows by transferring 1 integer amount to reserve to account for + // lack of fractional balance. + if senderNeedsBorrow && !recipientNeedsCarry { + borrowCoin := sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(1)) + if err := k.bk.SendCoinsFromAccountToModule( + ctx, + from, // sender borrowing + types.ModuleName, + sdk.NewCoins(borrowCoin), + ); err != nil { + return k.updateInsufficientFundsError(ctx, from, amt, err) + } + } + + // Case #3: NO sender borrow, recipient carry. + // Recipient's fractional balance carries over to integer balance by 1. + // Always send carry from reserve before receiving borrow from sender to + // ensure reserve always has sufficient balance starting from 0. + if !senderNeedsBorrow && recipientNeedsCarry { + reserveAddr := k.ak.GetModuleAddress(types.ModuleName) + + // We use SendCoins instead of SendCoinsFromModuleToAccount to avoid + // the blocked addrs check. Blocked accounts should not be checked in + // a SendCoins operation. Only SendCoinsFromModuleToAccount should check + // blocked addrs which is done by the parent SendCoinsFromModuleToAccount + // method. + carryCoin := sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(1)) + if err := k.bk.SendCoins( + ctx, + reserveAddr, + to, // recipient carrying + sdk.NewCoins(carryCoin), + ); err != nil { + // Panic instead of returning error, as this will only error + // with invalid state or logic. Reserve should always have + // sufficient balance to carry fractional coins. + panic(fmt.Errorf("failed to carry fractional coins to %s: %w", to, err)) + } + } + + // Case #4: NO sender borrow, NO recipient carry + // No additional operations required, as the transfer of fractional coins + // does not incur any integer borrow or carry. New fractional balances + // already calculated and just need to be set. + + // Persist new fractional balances to store. + k.SetFractionalBalance(ctx, from, senderNewFracBal) + k.SetFractionalBalance(ctx, to, recipientNewFracBal) + + return nil +} + +// subFromFractionalBalance subtracts a fractional amount from the provided +// current fractional balance, returning the new fractional balance and true if +// an integer borrow is required. +func subFromFractionalBalance( + currentFractionalBalance sdkmath.Int, + amountToSub sdkmath.Int, +) (sdkmath.Int, bool) { + // Enforce that currentFractionalBalance is not a full balance. + if currentFractionalBalance.GTE(types.ConversionFactor()) { + panic("currentFractionalBalance must be less than ConversionFactor") + } + + if amountToSub.GTE(types.ConversionFactor()) { + panic("amountToSub must be less than ConversionFactor") + } + + newFractionalBalance := currentFractionalBalance.Sub(amountToSub) + + // Insufficient fractional balance, so we need to borrow. + borrowRequired := newFractionalBalance.IsNegative() + + if borrowRequired { + // Borrowing 1 integer equivalent amount of fractional coins. We need to + // add 1 integer equivalent amount to the fractional balance otherwise + // the new fractional balance will be negative. + newFractionalBalance = newFractionalBalance.Add(types.ConversionFactor()) + } + + return newFractionalBalance, borrowRequired +} + +// addToFractionalBalance adds a fractional amount to the provided current +// fractional balance, returning the new fractional balance and true if a carry +// is required. +func addToFractionalBalance( + currentFractionalBalance sdkmath.Int, + amountToAdd sdkmath.Int, +) (sdkmath.Int, bool) { + // Enforce that currentFractionalBalance is not a full balance. + if currentFractionalBalance.GTE(types.ConversionFactor()) { + panic("currentFractionalBalance must be less than ConversionFactor") + } + + if amountToAdd.GTE(types.ConversionFactor()) { + panic("amountToAdd must be less than ConversionFactor") + } + + newFractionalBalance := currentFractionalBalance.Add(amountToAdd) + + // New balance exceeds max fractional balance, so we need to carry it over + // to the integer balance. + carryRequired := newFractionalBalance.GTE(types.ConversionFactor()) + + if carryRequired { + // Carry over to integer amount + newFractionalBalance = newFractionalBalance.Sub(types.ConversionFactor()) + } + + return newFractionalBalance, carryRequired +} + +// SendCoinsFromModuleToModule transfers coins from a ModuleAccount to another. +// It will panic if either module account does not exist. An error is returned +// if the recipient module is the x/precisebank module account or if sending the +// tokens fails. +func (k Keeper) SendCoinsFromAccountToModule( + ctx sdk.Context, + senderAddr sdk.AccAddress, + recipientModule string, + amt sdk.Coins, +) error { + recipientAcc := k.ak.GetModuleAccount(ctx, recipientModule) + if recipientAcc == nil { + panic(errorsmod.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", recipientModule)) + } + + if recipientModule == types.ModuleName { + return errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "module account %s is not allowed to receive funds", types.ModuleName) + } + + return k.SendCoins(ctx, senderAddr, recipientAcc.GetAddress(), amt) +} + +// SendCoinsFromModuleToAccount transfers coins from a ModuleAccount to an AccAddress. +// It will panic if the module account does not exist. An error is returned if +// the recipient address is blocked, if the sender is the x/precisebank module +// account, or if sending the tokens fails. +func (k Keeper) SendCoinsFromModuleToAccount( + ctx sdk.Context, + senderModule string, + recipientAddr sdk.AccAddress, + amt sdk.Coins, +) error { + // Identical panics to x/bank + senderAddr := k.ak.GetModuleAddress(senderModule) + if senderAddr == nil { + panic(errorsmod.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", senderModule)) + } + + // Custom error to prevent external modules from modifying x/precisebank + // balances. x/precisebank module account balance is for internal reserve + // use only. + if senderModule == types.ModuleName { + return errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "module account %s is not allowed to send funds", types.ModuleName) + } + + // Uses x/bank BlockedAddr, no need to modify. x/precisebank should be + // blocked. + if k.bk.BlockedAddr(recipientAddr) { + return errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "%s is not allowed to receive funds", recipientAddr) + } + + return k.SendCoins(ctx, senderAddr, recipientAddr, amt) +} + +// updateInsufficientFundsError returns a modified ErrInsufficientFunds with +// extended coin amounts if the error is due to insufficient funds. Otherwise, +// it returns the original error. This is used since x/bank transfers will +// return errors with integer coins, but we want the more accurate error that +// contains the full extended coin balance and send amounts. +func (k Keeper) updateInsufficientFundsError( + ctx sdk.Context, + addr sdk.AccAddress, + amt sdkmath.Int, + err error, +) error { + if !errors.Is(err, sdkerrors.ErrInsufficientFunds) { + return err + } + + // Check balance is sufficient + bal := k.GetBalance(ctx, addr, types.ExtendedCoinDenom) + coin := sdk.NewCoin(types.ExtendedCoinDenom, amt) + + // TODO: This checks spendable coins and returns error with spendable + // coins, not full balance. If GetBalance() is modified to return the + // full, including locked, balance then this should be updated to deduct + // locked coins. + + // Use sdk.NewCoins() so that it removes empty balances - ie. prints + // empty string if balance is 0. This is to match x/bank behavior. + spendable := sdk.NewCoins(bal) + + return errorsmod.Wrapf( + sdkerrors.ErrInsufficientFunds, + "spendable balance %s is smaller than %s", + spendable, coin, + ) +} diff --git a/x/precisebank/keeper/send_integration_test.go b/x/precisebank/keeper/send_integration_test.go new file mode 100644 index 00000000..9707ec49 --- /dev/null +++ b/x/precisebank/keeper/send_integration_test.go @@ -0,0 +1,781 @@ +package keeper_test + +import ( + "fmt" + "testing" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/precisebank/keeper" + "github.com/0glabs/0g-chain/x/precisebank/testutil" + "github.com/0glabs/0g-chain/x/precisebank/types" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + "github.com/stretchr/testify/suite" +) + +type sendIntegrationTestSuite struct { + testutil.Suite +} + +func (suite *sendIntegrationTestSuite) SetupTest() { + suite.Suite.SetupTest() +} + +func TestSendIntegrationTestSuite(t *testing.T) { + suite.Run(t, new(sendIntegrationTestSuite)) +} + +func (suite *sendIntegrationTestSuite) TestSendCoinsFromAccountToModule_MatchingErrors() { + // No specific errors for SendCoinsFromAccountToModule, only 1 panic if + // the module account does not exist + + tests := []struct { + name string + sender sdk.AccAddress + recipientModule string + sendAmount sdk.Coins + wantPanic string + }{ + // SendCoinsFromAccountToModule specific errors/panics + { + "missing module account - passthrough", + sdk.AccAddress([]byte{2}), + "cat", + cs(c("usdc", 1000)), + "module account cat does not exist: unknown address", + }, + { + "missing module account - extended", + sdk.AccAddress([]byte{2}), + "cat", + cs(c(types.ExtendedCoinDenom, 1000)), + "module account cat does not exist: unknown address", + }, + } + + for _, tt := range tests { + suite.Run(tt.name, func() { + // Reset + suite.SetupTest() + + suite.Require().NotEmpty(tt.wantPanic, "test case must have a wantPanic") + + suite.Require().PanicsWithError(tt.wantPanic, func() { + suite.BankKeeper.SendCoinsFromAccountToModule(suite.Ctx, tt.sender, tt.recipientModule, tt.sendAmount) + }, "wantPanic should match x/bank SendCoinsFromAccountToModule panic") + + suite.Require().PanicsWithError(tt.wantPanic, func() { + suite.Keeper.SendCoinsFromAccountToModule(suite.Ctx, tt.sender, tt.recipientModule, tt.sendAmount) + }, "x/precisebank panic should match x/bank SendCoinsFromAccountToModule panic") + }) + } +} + +func (suite *sendIntegrationTestSuite) TestSendCoinsFromModuleToAccount_MatchingErrors() { + // Ensure errors match x/bank errors AND panics. This needs to be well + // tested before SendCoins as all send tests rely on this to initialize + // account balances. + // No unit test with mock x/bank for SendCoinsFromModuleToAccount since + // we only are testing the errors/panics specific to the method and + // remaining logic is the same as SendCoins. + + blockedMacAddrs := suite.App.GetBlockedMaccAddrs() + precisebankAddr := suite.AccountKeeper.GetModuleAddress(types.ModuleName) + + var blockedAddr sdk.AccAddress + // Get the first blocked address + for addr, isBlocked := range blockedMacAddrs { + // Skip x/precisebank module account + if addr == precisebankAddr.String() { + continue + } + + if isBlocked { + blockedAddr = sdk.MustAccAddressFromBech32(addr) + break + } + } + + // We need a ModuleName of another module account to send funds from. + // x/precisebank is blocked from use with SendCoinsFromModuleToAccount as we + // don't want external modules to modify x/precisebank balances. + var senderModuleName string + macPerms := app.GetMaccPerms() + for moduleName := range macPerms { + if moduleName != types.ModuleName { + senderModuleName = moduleName + } + } + + suite.Require().NotEmpty(blockedAddr, "no blocked addresses found") + suite.Require().NotEmpty(senderModuleName, "no sender module name found") + + tests := []struct { + name string + senderModule string + recipient sdk.AccAddress + sendAmount sdk.Coins + wantErr string + wantPanic string + }{ + // SendCoinsFromModuleToAccount specific errors/panics + { + "missing module account - passthrough", + "cat", + sdk.AccAddress([]byte{2}), + cs(c("usdc", 1000)), + "", + "module account cat does not exist: unknown address", + }, + { + "missing module account - extended", + "cat", + sdk.AccAddress([]byte{2}), + cs(c(types.ExtendedCoinDenom, 1000)), + "", + "module account cat does not exist: unknown address", + }, + { + "blocked recipient address - passthrough", + senderModuleName, + blockedAddr, + cs(c("usdc", 1000)), + fmt.Sprintf("%s is not allowed to receive funds: unauthorized", blockedAddr.String()), + "", + }, + { + "blocked recipient address - extended", + senderModuleName, + blockedAddr, + cs(c(types.ExtendedCoinDenom, 1000)), + fmt.Sprintf("%s is not allowed to receive funds: unauthorized", blockedAddr.String()), + "", + }, + // SendCoins specific errors/panics + { + "invalid coins", + senderModuleName, + sdk.AccAddress([]byte{2}), + sdk.Coins{sdk.Coin{Denom: "ukava", Amount: sdk.NewInt(-1)}}, + "-1ukava: invalid coins", + "", + }, + { + "insufficient balance - passthrough", + senderModuleName, + sdk.AccAddress([]byte{2}), + cs(c(types.IntegerCoinDenom, 1000)), + "spendable balance is smaller than 1000ukava: insufficient funds", + "", + }, + { + "insufficient balance - extended", + senderModuleName, + sdk.AccAddress([]byte{2}), + // We can still test insufficient bal errors with "akava" since + // we also expect it to not exist in x/bank + cs(c(types.ExtendedCoinDenom, 1000)), + "spendable balance is smaller than 1000akava: insufficient funds", + "", + }, + } + + for _, tt := range tests { + suite.Run(tt.name, func() { + // Reset + suite.SetupTest() + + if tt.wantPanic == "" && tt.wantErr == "" { + suite.FailNow("test case must have a wantErr or wantPanic") + } + + if tt.wantPanic != "" { + suite.Require().Empty(tt.wantErr, "test case must not have a wantErr if wantPanic is set") + + suite.Require().PanicsWithError(tt.wantPanic, func() { + suite.BankKeeper.SendCoinsFromModuleToAccount(suite.Ctx, tt.senderModule, tt.recipient, tt.sendAmount) + }, "wantPanic should match x/bank SendCoinsFromModuleToAccount panic") + + suite.Require().PanicsWithError(tt.wantPanic, func() { + suite.Keeper.SendCoinsFromModuleToAccount(suite.Ctx, tt.senderModule, tt.recipient, tt.sendAmount) + }, "x/precisebank panic should match x/bank SendCoinsFromModuleToAccount panic") + } + + if tt.wantErr != "" { + bankErr := suite.BankKeeper.SendCoinsFromModuleToAccount(suite.Ctx, tt.senderModule, tt.recipient, tt.sendAmount) + suite.Require().Error(bankErr) + suite.Require().EqualError(bankErr, tt.wantErr, "expected error should match x/bank SendCoins error") + + pbankErr := suite.Keeper.SendCoinsFromModuleToAccount(suite.Ctx, tt.senderModule, tt.recipient, tt.sendAmount) + suite.Require().Error(pbankErr) + // Compare strings instead of errors, as error stack is still different + suite.Require().Equal( + bankErr.Error(), + pbankErr.Error(), + "x/precisebank error should match x/bank SendCoins error", + ) + } + }) + } +} + +func (suite *sendIntegrationTestSuite) TestSendCoins_MatchingErrors() { + // Ensure errors match x/bank errors + + tests := []struct { + name string + initialAmount sdk.Coins + sendAmount sdk.Coins + wantErr string + }{ + { + "invalid coins", + cs(), + sdk.Coins{sdk.Coin{Denom: "ukava", Amount: sdk.NewInt(-1)}}, + "-1ukava: invalid coins", + }, + { + "insufficient empty balance - passthrough", + cs(), + cs(c(types.IntegerCoinDenom, 1000)), + "spendable balance is smaller than 1000ukava: insufficient funds", + }, + { + "insufficient empty balance - extended", + cs(), + // We can still test insufficient bal errors with "akava" since + // we also expect it to not exist in x/bank + cs(c(types.ExtendedCoinDenom, 1000)), + "spendable balance is smaller than 1000akava: insufficient funds", + }, + { + "insufficient non-empty balance - passthrough", + cs(c(types.IntegerCoinDenom, 100), c("usdc", 1000)), + cs(c(types.IntegerCoinDenom, 1000)), + "spendable balance 100ukava is smaller than 1000ukava: insufficient funds", + }, + // non-empty akava transfer error is tested in SendCoins, not here since + // x/bank doesn't hold akava + } + + for _, tt := range tests { + suite.Run(tt.name, func() { + // Reset + suite.SetupTest() + sender := sdk.AccAddress([]byte{1}) + recipient := sdk.AccAddress([]byte{2}) + + suite.Require().NotEmpty(tt.wantErr, "test case must have a wantErr") + + suite.MintToAccount(sender, tt.initialAmount) + + bankErr := suite.BankKeeper.SendCoins(suite.Ctx, sender, recipient, tt.sendAmount) + suite.Require().Error(bankErr) + suite.Require().EqualError(bankErr, tt.wantErr, "expected error should match x/bank SendCoins error") + + pbankErr := suite.Keeper.SendCoins(suite.Ctx, sender, recipient, tt.sendAmount) + suite.Require().Error(pbankErr) + // Compare strings instead of errors, as error stack is still different + suite.Require().Equal( + bankErr.Error(), + pbankErr.Error(), + "x/precisebank error should match x/bank SendCoins error", + ) + }) + } +} + +func (suite *sendIntegrationTestSuite) TestSendCoins() { + // SendCoins is tested mostly in this integration test, as a unit test with + // mocked BankKeeper overcomplicates expected keepers and makes initializing + // balances very complex. + + tests := []struct { + name string + giveStartBalSender sdk.Coins + giveStartBalRecipient sdk.Coins + giveAmt sdk.Coins + wantErr string + }{ + { + "insufficient balance error denom matches", + cs(c(types.ExtendedCoinDenom, 10), c("usdc", 1000)), + cs(), + cs(c(types.ExtendedCoinDenom, 1000)), + "spendable balance 10akava is smaller than 1000akava: insufficient funds", + }, + { + "passthrough - unrelated", + cs(c("cats", 1000)), + cs(), + cs(c("cats", 1000)), + "", + }, + { + "passthrough - integer denom", + cs(c(types.IntegerCoinDenom, 1000)), + cs(), + cs(c(types.IntegerCoinDenom, 1000)), + "", + }, + { + "passthrough & extended", + cs(c(types.IntegerCoinDenom, 1000)), + cs(), + cs(c(types.IntegerCoinDenom, 10), c(types.ExtendedCoinDenom, 1)), + "", + }, + { + "akava send - 1akava to 0 balance", + // Starting balances + cs(ci(types.ExtendedCoinDenom, types.ConversionFactor().MulRaw(5))), + cs(), + // Send amount + cs(c(types.ExtendedCoinDenom, 1)), // akava + "", + }, + { + "sender borrow from integer", + // 1ukava, 0 fractional + cs(ci(types.ExtendedCoinDenom, types.ConversionFactor())), + cs(), + // Send 1 with 0 fractional balance + cs(c(types.ExtendedCoinDenom, 1)), + "", + }, + { + "sender borrow from integer - max fractional amount", + // 1ukava, 0 fractional + cs(ci(types.ExtendedCoinDenom, types.ConversionFactor())), + cs(), + // Max fractional amount + cs(ci(types.ExtendedCoinDenom, types.ConversionFactor().SubRaw(1))), + "", + }, + { + "receiver carry", + cs(c(types.ExtendedCoinDenom, 1000)), + // max fractional amount, carries over to integer + cs(ci(types.ExtendedCoinDenom, types.ConversionFactor().SubRaw(1))), + cs(c(types.ExtendedCoinDenom, 1)), + "", + }, + { + "receiver carry - max fractional amount", + cs(ci(types.ExtendedCoinDenom, types.ConversionFactor().MulRaw(5))), + // max fractional amount, carries over to integer + cs(ci(types.ExtendedCoinDenom, types.ConversionFactor().SubRaw(1))), + cs(ci(types.ExtendedCoinDenom, types.ConversionFactor().SubRaw(1))), + "", + }, + } + + for _, tt := range tests { + suite.Run(tt.name, func() { + suite.SetupTest() + + sender := sdk.AccAddress([]byte{1}) + recipient := sdk.AccAddress([]byte{2}) + + // Initialize balances + suite.MintToAccount(sender, tt.giveStartBalSender) + suite.MintToAccount(recipient, tt.giveStartBalRecipient) + + senderBalBefore := suite.GetAllBalances(sender) + recipientBalBefore := suite.GetAllBalances(recipient) + + err := suite.Keeper.SendCoins(suite.Ctx, sender, recipient, tt.giveAmt) + if tt.wantErr != "" { + suite.Require().Error(err) + suite.Require().EqualError(err, tt.wantErr) + return + } + + suite.Require().NoError(err) + + // Check balances + senderBalAfter := suite.GetAllBalances(sender) + recipientBalAfter := suite.GetAllBalances(recipient) + + // Convert send amount coins to extended coins. i.e. if send coins + // includes ukava, convert it so that its the equivalent akava + // amount so its easier to compare. Compare extended coins only. + sendAmountFullExtended := tt.giveAmt + sendAmountInteger := tt.giveAmt.AmountOf(types.IntegerCoinDenom) + if !sendAmountInteger.IsZero() { + integerCoin := sdk.NewCoin(types.IntegerCoinDenom, sendAmountInteger) + sendAmountFullExtended = sendAmountFullExtended.Sub(integerCoin) + + // Add equivalent extended coin + extendedCoinAmount := sendAmountInteger.Mul(types.ConversionFactor()) + extendedCoin := sdk.NewCoin(types.ExtendedCoinDenom, extendedCoinAmount) + sendAmountFullExtended = sendAmountFullExtended.Add(extendedCoin) + } + + suite.Require().Equal( + senderBalBefore.Sub(sendAmountFullExtended...), + senderBalAfter, + ) + + suite.Require().Equal( + recipientBalBefore.Add(sendAmountFullExtended...), + recipientBalAfter, + ) + + invariantFn := keeper.AllInvariants(suite.Keeper) + res, stop := invariantFn(suite.Ctx) + suite.Require().False(stop, "invariants should not stop") + suite.Require().Empty(res, "invariants should not return any messages") + + // Check events + + // FULL akava equivalent, including ukava only/mixed sends + sendExtendedAmount := sdk.NewCoin( + types.ExtendedCoinDenom, + sendAmountFullExtended.AmountOf(types.ExtendedCoinDenom), + ) + extCoins := sdk.NewCoins(sendExtendedAmount) + + // No extra events if not sending akava + if sendExtendedAmount.IsZero() { + return + } + + extendedEvent := sdk.NewEvent( + banktypes.EventTypeTransfer, + sdk.NewAttribute(banktypes.AttributeKeyRecipient, recipient.String()), + sdk.NewAttribute(banktypes.AttributeKeySender, sender.String()), + sdk.NewAttribute(sdk.AttributeKeyAmount, sendExtendedAmount.String()), + ) + + expReceivedEvent := banktypes.NewCoinReceivedEvent( + recipient, + extCoins, + ) + + expSentEvent := banktypes.NewCoinSpentEvent( + sender, + extCoins, + ) + + events := suite.Ctx.EventManager().Events() + + suite.Require().Contains(events, extendedEvent) + suite.Require().Contains(events, expReceivedEvent) + suite.Require().Contains(events, expSentEvent) + }) + } +} + +func (suite *sendIntegrationTestSuite) TestSendCoins_Matrix() { + // SendCoins is tested mostly in this integration test, as a unit test with + // mocked BankKeeper overcomplicates expected keepers and makes initializing + // balances very complex. + + type startBalance struct { + name string + bal sdk.Coins + } + + // Run through each combination of start sender/recipient balance & send amt + // Test matrix fields: + startBalances := []startBalance{ + {"empty", cs()}, + {"integer only", cs(c(types.IntegerCoinDenom, 1000))}, + {"extended only", cs(c(types.ExtendedCoinDenom, 1000))}, + {"integer & extended", cs(c(types.IntegerCoinDenom, 1000), c(types.ExtendedCoinDenom, 1000))}, + {"integer & extended - max fractional", cs(c(types.IntegerCoinDenom, 1000), ci(types.ExtendedCoinDenom, types.ConversionFactor().SubRaw(1)))}, + {"integer & extended - min fractional", cs(c(types.IntegerCoinDenom, 1000), c(types.ExtendedCoinDenom, 1))}, + } + + sendAmts := []struct { + name string + amt sdk.Coins + }{ + { + "empty", + cs(), + }, + { + "integer only", + cs(c(types.IntegerCoinDenom, 10)), + }, + { + "extended only", + cs(c(types.ExtendedCoinDenom, 10)), + }, + { + "integer & extended", + cs(c(types.IntegerCoinDenom, 10), c(types.ExtendedCoinDenom, 1000)), + }, + { + "integer & extended - max fractional", + cs(c(types.IntegerCoinDenom, 10), ci(types.ExtendedCoinDenom, types.ConversionFactor().SubRaw(1))), + }, + { + "integer & extended - min fractional", + cs(c(types.IntegerCoinDenom, 10), c(types.ExtendedCoinDenom, 1)), + }, + } + + for _, senderStartBal := range startBalances { + for _, recipientStartBal := range startBalances { + for _, sendAmt := range sendAmts { + testName := fmt.Sprintf( + "%s -> %s (%s -> %s), send %s (%s)", + senderStartBal.name, senderStartBal.bal, + recipientStartBal.name, recipientStartBal.bal, + sendAmt.name, sendAmt.amt, + ) + + suite.Run(testName, func() { + suite.SetupTest() + + sender := sdk.AccAddress([]byte{1}) + recipient := sdk.AccAddress([]byte{2}) + + // Initialize balances + suite.MintToAccount(sender, senderStartBal.bal) + suite.MintToAccount(recipient, recipientStartBal.bal) + + // balances & send amount will only contain total equivalent + // extended coins and no integer coins so its easier to compare + senderBalBefore := suite.GetAllBalances(sender) + recipientBalBefore := suite.GetAllBalances(recipient) + + sendAmtNormalized := testutil.ConvertCoinsToExtendedCoinDenom(sendAmt.amt) + + err := suite.Keeper.SendCoins(suite.Ctx, sender, recipient, sendAmt.amt) + + hasSufficientBal := senderBalBefore.IsAllGTE(sendAmtNormalized) + + if hasSufficientBal { + suite.Require().NoError(err) + } else { + suite.Require().Error(err, "expected insufficient funds error") + // No balance checks if insufficient funds + return + } + + // Check balances + senderBalAfter := suite.GetAllBalances(sender) + recipientBalAfter := suite.GetAllBalances(recipient) + + // Convert send amount coins to extended coins. i.e. if send coins + // includes ukava, convert it so that its the equivalent akava + // amount so its easier to compare. Compare extended coins only. + + suite.Require().Equal( + senderBalBefore.Sub(sendAmtNormalized...), + senderBalAfter, + ) + + suite.Require().Equal( + recipientBalBefore.Add(sendAmtNormalized...), + recipientBalAfter, + ) + + invariantFn := keeper.AllInvariants(suite.Keeper) + res, stop := invariantFn(suite.Ctx) + suite.Require().False(stop, "invariants should not stop") + suite.Require().Empty(res, "invariants should not return any messages") + }) + } + } + } +} + +func (suite *sendIntegrationTestSuite) TestSendCoinsFromAccountToModule() { + // Ensure recipient correctly matches the specified module account. Specific + // send amount and cases are handled by SendCoins() tests, so we are only + // checking SendCoinsFromAccountToModule specific behavior here. + + sender := sdk.AccAddress([]byte{1}) + recipientModule := minttypes.ModuleName + recipientAddr := suite.AccountKeeper.GetModuleAddress(recipientModule) + + sendAmt := cs(c(types.ExtendedCoinDenom, 1000)) + + suite.MintToAccount(sender, sendAmt) + + err := suite.Keeper.SendCoinsFromAccountToModule( + suite.Ctx, + sender, + recipientModule, + sendAmt, + ) + suite.Require().NoError(err) + + // Check balances + senderBalAfter := suite.GetAllBalances(sender) + recipientBalAfter := suite.GetAllBalances(recipientAddr) + + suite.Require().Equal( + cs(), + senderBalAfter, + ) + + suite.Require().Equal( + sendAmt, + recipientBalAfter, + ) +} + +func (suite *sendIntegrationTestSuite) TestSendCoinsFromAccountToModule_BlockedRecipientCarry() { + // Carrying to module account balance. This tests that SendCoinsFromAccountToModule + // does not fail when sending to a blocked module account. + + sender := sdk.AccAddress([]byte{1}) + + sendAmt := cs(c(types.ExtendedCoinDenom, 1000)) + sendAmt2 := cs(ci(types.ExtendedCoinDenom, types.ConversionFactor().SubRaw(10))) + + suite.MintToAccount(sender, sendAmt.Add(sendAmt2...)) + + err := suite.Keeper.SendCoinsFromAccountToModule( + suite.Ctx, + sender, + authtypes.FeeCollectorName, + sendAmt, + ) + suite.Require().NoError(err) + + // Trigger carry for fee_collector module account + err = suite.Keeper.SendCoinsFromAccountToModule( + suite.Ctx, + sender, + authtypes.FeeCollectorName, + sendAmt2, + ) + suite.Require().NoError(err) +} + +func (suite *sendIntegrationTestSuite) TestSendCoins_BlockedRecipientCarry() { + // Same test as TestSendCoinsFromModuleToAccount_Blocked, but with SendCoins + // which also should not fail when sending to a blocked module account. + sender := sdk.AccAddress([]byte{1}) + + sendAmt := cs(c(types.ExtendedCoinDenom, 1000)) + sendAmt2 := cs(ci(types.ExtendedCoinDenom, types.ConversionFactor().SubRaw(10))) + + suite.MintToAccount(sender, sendAmt.Add(sendAmt2...)) + + recipient := suite.App.GetAccountKeeper().GetModuleAddress(authtypes.FeeCollectorName) + + err := suite.Keeper.SendCoins( + suite.Ctx, + sender, + recipient, + sendAmt, + ) + suite.Require().NoError(err) + + // Trigger carry for fee_collector module account + err = suite.Keeper.SendCoins( + suite.Ctx, + sender, + recipient, + sendAmt2, + ) + suite.Require().NoError(err) +} + +func (suite *sendIntegrationTestSuite) TestSendCoinsFromModuleToAccount() { + // Ensure sender correctly matches the specified module account. Opposite + // of SendCoinsFromAccountToModule, so we are only checking the correct + // addresses are being used. + + senderModule := "community" + senderAddr := suite.AccountKeeper.GetModuleAddress(senderModule) + + recipient := sdk.AccAddress([]byte{1}) + + sendAmt := cs(c(types.ExtendedCoinDenom, 1000)) + + suite.MintToAccount(senderAddr, sendAmt) + + err := suite.Keeper.SendCoinsFromModuleToAccount( + suite.Ctx, + senderModule, + recipient, + sendAmt, + ) + suite.Require().NoError(err) + + // Check balances + senderBalAfter := suite.GetAllBalances(senderAddr) + recipientBalAfter := suite.GetAllBalances(recipient) + + suite.Require().Equal( + cs(), + senderBalAfter, + ) + + suite.Require().Equal( + sendAmt, + recipientBalAfter, + ) +} + +func FuzzSendCoins(f *testing.F) { + f.Add(uint64(100), uint64(0), uint64(2)) + f.Add(uint64(100), uint64(100), uint64(5)) + f.Add(types.ConversionFactor().Uint64(), uint64(0), uint64(500)) + f.Add( + types.ConversionFactor().MulRaw(2).AddRaw(123948723).Uint64(), + types.ConversionFactor().MulRaw(2).Uint64(), + types.ConversionFactor().Uint64(), + ) + + f.Fuzz(func( + t *testing.T, + startBalSender uint64, + startBalReceiver uint64, + sendAmount uint64, + ) { + // Manually setup test suite since no direct Fuzz support in test suites + suite := new(sendIntegrationTestSuite) + suite.SetT(t) + suite.SetS(suite) + suite.SetupTest() + + sender := sdk.AccAddress([]byte{1}) + recipient := sdk.AccAddress([]byte{2}) + + // Initial balances + suite.MintToAccount(sender, cs(c(types.ExtendedCoinDenom, int64(startBalSender)))) + suite.MintToAccount(recipient, cs(c(types.ExtendedCoinDenom, int64(startBalReceiver)))) + + // Send amount + sendCoins := cs(c(types.ExtendedCoinDenom, int64(sendAmount))) + err := suite.Keeper.SendCoins(suite.Ctx, sender, recipient, sendCoins) + if startBalSender < sendAmount { + suite.Require().Error(err, "expected insufficient funds error") + return + } + + suite.Require().NoError(err) + + // Check FULL balances + balSender := suite.GetAllBalances(sender) + balReceiver := suite.GetAllBalances(recipient) + + suite.Require().Equal( + startBalSender-sendAmount, + balSender.AmountOf(types.ExtendedCoinDenom).Uint64(), + ) + suite.Require().Equal( + startBalReceiver+sendAmount, + balReceiver.AmountOf(types.ExtendedCoinDenom).Uint64(), + ) + + // Run Invariants to ensure remainder is backing all minted fractions + // and in a valid state + allInvariantsFn := keeper.AllInvariants(suite.Keeper) + res, stop := allInvariantsFn(suite.Ctx) + suite.Require().False(stop, "invariant should not be broken") + suite.Require().Empty(res, "unexpected invariant message: %s", res) + }) +} diff --git a/x/precisebank/keeper/send_test.go b/x/precisebank/keeper/send_test.go new file mode 100644 index 00000000..bbcfc5a3 --- /dev/null +++ b/x/precisebank/keeper/send_test.go @@ -0,0 +1,47 @@ +package keeper_test + +import ( + "testing" + + "github.com/0glabs/0g-chain/x/precisebank/types" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/stretchr/testify/require" +) + +func TestSendCoinsFromAccountToModule_BlockedReserve(t *testing.T) { + // Other modules shouldn't be able to send x/precisebank coins as the module + // account balance is for internal reserve use only. + + td := NewMockedTestData(t) + td.ak.EXPECT(). + GetModuleAccount(td.ctx, types.ModuleName). + Return(authtypes.NewModuleAccount( + authtypes.NewBaseAccountWithAddress(sdk.AccAddress{100}), + types.ModuleName, + )). + Once() + + fromAddr := sdk.AccAddress([]byte{1}) + err := td.keeper.SendCoinsFromAccountToModule(td.ctx, fromAddr, types.ModuleName, cs(c("busd", 1000))) + + require.Error(t, err) + require.EqualError(t, err, "module account precisebank is not allowed to receive funds: unauthorized") +} + +func TestSendCoinsFromModuleToAccount_BlockedReserve(t *testing.T) { + // Other modules shouldn't be able to send x/precisebank module account + // funds. + + td := NewMockedTestData(t) + td.ak.EXPECT(). + GetModuleAddress(types.ModuleName). + Return(sdk.AccAddress{100}). + Once() + + toAddr := sdk.AccAddress([]byte{1}) + err := td.keeper.SendCoinsFromModuleToAccount(td.ctx, types.ModuleName, toAddr, cs(c("busd", 1000))) + + require.Error(t, err) + require.EqualError(t, err, "module account precisebank is not allowed to send funds: unauthorized") +} diff --git a/x/precisebank/keeper/view.go b/x/precisebank/keeper/view.go new file mode 100644 index 00000000..2073495b --- /dev/null +++ b/x/precisebank/keeper/view.go @@ -0,0 +1,75 @@ +package keeper + +import ( + sdkmath "cosmossdk.io/math" + "github.com/0glabs/0g-chain/x/precisebank/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// GetBalance returns the balance of a specific denom for an address. This will +// return the extended balance for the ExtendedCoinDenom, and the regular +// balance for all other denoms. +func (k Keeper) GetBalance( + ctx sdk.Context, + addr sdk.AccAddress, + denom string, +) sdk.Coin { + // Module balance should display as empty for extended denom. Module + // balances are **only** for the reserve which backs the fractional + // balances. Returning the backing balances if querying extended denom would + // result in a double counting of the fractional balances. + if denom == types.ExtendedCoinDenom && addr.Equals(k.ak.GetModuleAddress(types.ModuleName)) { + return sdk.NewCoin(denom, sdkmath.ZeroInt()) + } + + // Pass through to x/bank for denoms except ExtendedCoinDenom + if denom != types.ExtendedCoinDenom { + return k.bk.GetBalance(ctx, addr, denom) + } + + // x/bank for integer balance - full balance, including locked + integerCoins := k.bk.GetBalance(ctx, addr, types.IntegerCoinDenom) + + // x/precisebank for fractional balance + fractionalAmount := k.GetFractionalBalance(ctx, addr) + + // (Integer * ConversionFactor) + Fractional + fullAmount := integerCoins. + Amount. + Mul(types.ConversionFactor()). + Add(fractionalAmount) + + return sdk.NewCoin(types.ExtendedCoinDenom, fullAmount) +} + +// SpendableCoins returns the total balances of spendable coins for an account +// by address. If the account has no spendable coins, an empty Coins slice is +// returned. +func (k Keeper) SpendableCoin( + ctx sdk.Context, + addr sdk.AccAddress, + denom string, +) sdk.Coin { + // Same as GetBalance, extended denom balances are transparent to consumers. + if denom == types.ExtendedCoinDenom && addr.Equals(k.ak.GetModuleAddress(types.ModuleName)) { + return sdk.NewCoin(denom, sdkmath.ZeroInt()) + } + + // Pass through to x/bank for denoms except ExtendedCoinDenom + if denom != types.ExtendedCoinDenom { + return k.bk.SpendableCoin(ctx, addr, denom) + } + + // x/bank for integer balance - excluding locked + integerCoin := k.bk.SpendableCoin(ctx, addr, types.IntegerCoinDenom) + + // x/precisebank for fractional balance + fractionalAmount := k.GetFractionalBalance(ctx, addr) + + // Spendable = (Integer * ConversionFactor) + Fractional + fullAmount := integerCoin.Amount. + Mul(types.ConversionFactor()). + Add(fractionalAmount) + + return sdk.NewCoin(types.ExtendedCoinDenom, fullAmount) +} diff --git a/x/precisebank/keeper/view_integration_test.go b/x/precisebank/keeper/view_integration_test.go new file mode 100644 index 00000000..4241bb40 --- /dev/null +++ b/x/precisebank/keeper/view_integration_test.go @@ -0,0 +1,202 @@ +package keeper_test + +import ( + "testing" + + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" + + "github.com/0glabs/0g-chain/x/precisebank/testutil" + "github.com/0glabs/0g-chain/x/precisebank/types" + "github.com/stretchr/testify/suite" +) + +type viewIntegrationTestSuite struct { + testutil.Suite +} + +func (suite *viewIntegrationTestSuite) SetupTest() { + suite.Suite.SetupTest() +} + +func TestViewIntegrationTestSuite(t *testing.T) { + suite.Run(t, new(viewIntegrationTestSuite)) +} + +func (suite *viewIntegrationTestSuite) TestKeeper_SpendableCoin() { + tests := []struct { + name string + giveDenom string // queried denom for balance + + giveBankBal sdk.Coins // full balance + giveFractionalBal sdkmath.Int // stored fractional balance for giveAddr + giveLockedCoins sdk.Coins // locked coins + + wantSpendableBal sdk.Coin + }{ + { + "extended denom, no fractional - locked coins", + types.ExtendedCoinDenom, + // queried bank balance in ukava when querying for akava + sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(1000))), + sdkmath.ZeroInt(), + sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(10))), + // (integer + fractional) - locked + sdk.NewCoin( + types.ExtendedCoinDenom, + types.ConversionFactor().MulRaw(1000-10), + ), + }, + { + "extended denom, with fractional - locked coins", + types.ExtendedCoinDenom, + // queried bank balance in ukava when querying for akava + sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(1000))), + sdkmath.NewInt(5000), + sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(10))), + sdk.NewCoin( + types.ExtendedCoinDenom, + // (integer - locked) + fractional + types.ConversionFactor().MulRaw(1000-10).AddRaw(5000), + ), + }, + { + "non-extended denom - ukava returns ukava", + types.IntegerCoinDenom, + sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(1000))), + sdkmath.ZeroInt(), + sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(10))), + sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(990)), + }, + { + "non-extended denom, with fractional - ukava returns ukava", + types.IntegerCoinDenom, + sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(1000))), + // does not affect balance + sdkmath.NewInt(100), + sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(10))), + sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(990)), + }, + } + + for _, tt := range tests { + suite.Run(tt.name, func() { + suite.SetupTest() + + addr := sdk.AccAddress([]byte("test-address")) + + suite.MintToAccount(addr, tt.giveBankBal) + + // Set fractional balance in store before query + suite.Keeper.SetFractionalBalance(suite.Ctx, addr, tt.giveFractionalBal) + + // Add some locked coins + acc := suite.AccountKeeper.GetAccount(suite.Ctx, addr) + if acc == nil { + acc = authtypes.NewBaseAccount(addr, nil, 0, 0) + } + + vestingAcc := vestingtypes.NewPeriodicVestingAccount( + acc.(*authtypes.BaseAccount), + tt.giveLockedCoins, + suite.Ctx.BlockTime().Unix(), + vestingtypes.Periods{ + vestingtypes.Period{ + Length: 100, + Amount: tt.giveLockedCoins, + }, + }, + ) + suite.AccountKeeper.SetAccount(suite.Ctx, vestingAcc) + + fetchedLockedCoins := vestingAcc.LockedCoins(suite.Ctx.BlockTime()) + suite.Require().Equal( + tt.giveLockedCoins, + fetchedLockedCoins, + "locked coins should be matching at current block time", + ) + + spendableCoinsWithLocked := suite.Keeper.SpendableCoin(suite.Ctx, addr, tt.giveDenom) + + suite.Require().Equalf( + tt.wantSpendableBal, + spendableCoinsWithLocked, + "expected spendable coins of denom %s", + tt.giveDenom, + ) + }) + } +} + +func (suite *viewIntegrationTestSuite) TestKeeper_HiddenReserve() { + // Reserve balances should not be shown to consumers of x/precisebank, as it + // represents the fractional balances of accounts. + + moduleAddr := authtypes.NewModuleAddress(types.ModuleName) + addr1 := sdk.AccAddress{1} + + // Make the reserve hold a non-zero balance + // Mint fractional coins to an account, which should cause a mint of 1 + // integer coin to the reserve to back it. + extCoin := sdk.NewCoin(types.ExtendedCoinDenom, types.ConversionFactor().AddRaw(1000)) + unrelatedCoin := sdk.NewCoin("unrelated", sdk.NewInt(1000)) + suite.MintToAccount( + addr1, + sdk.NewCoins( + extCoin, + unrelatedCoin, + ), + ) + + // Check underlying x/bank balance for reserve + reserveIntCoin := suite.BankKeeper.GetBalance(suite.Ctx, moduleAddr, types.IntegerCoinDenom) + suite.Require().Equal( + sdkmath.NewInt(1), + reserveIntCoin.Amount, + "reserve should hold 1 integer coin", + ) + + tests := []struct { + name string + giveAddr sdk.AccAddress + giveDenom string + wantAmount sdkmath.Int + }{ + { + "reserve account - hidden extended denom", + moduleAddr, + types.ExtendedCoinDenom, + sdkmath.ZeroInt(), + }, + { + "reserve account - visible integer denom", + moduleAddr, + types.IntegerCoinDenom, + sdkmath.OneInt(), + }, + { + "user account - visible extended denom", + addr1, + types.ExtendedCoinDenom, + extCoin.Amount, + }, + { + "user account - visible integer denom", + addr1, + types.IntegerCoinDenom, + extCoin.Amount.Quo(types.ConversionFactor()), + }, + } + + for _, tt := range tests { + suite.Run(tt.name, func() { + coin := suite.Keeper.GetBalance(suite.Ctx, tt.giveAddr, tt.giveDenom) + suite.Require().Equal(tt.wantAmount.Int64(), coin.Amount.Int64()) + + spendableCoin := suite.Keeper.SpendableCoin(suite.Ctx, tt.giveAddr, tt.giveDenom) + suite.Require().Equal(tt.wantAmount.Int64(), spendableCoin.Amount.Int64()) + }) + } +} diff --git a/x/precisebank/keeper/view_test.go b/x/precisebank/keeper/view_test.go new file mode 100644 index 00000000..01179c06 --- /dev/null +++ b/x/precisebank/keeper/view_test.go @@ -0,0 +1,296 @@ +package keeper_test + +import ( + "testing" + + sdkmath "cosmossdk.io/math" + "github.com/0glabs/0g-chain/x/precisebank/types" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/stretchr/testify/require" +) + +func TestKeeper_GetBalance(t *testing.T) { + tests := []struct { + name string + giveDenom string // queried denom for balance + + giveBankBal sdk.Coins // mocked bank balance for giveAddr + giveFractionalBal sdkmath.Int // stored fractional balance for giveAddr + + wantBal sdk.Coin + }{ + { + "extended denom - no fractional balance", + types.ExtendedCoinDenom, + // queried bank balance in ukava when querying for akava + sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(1000))), + sdkmath.ZeroInt(), + // integer + fractional + sdk.NewCoin(types.ExtendedCoinDenom, sdk.NewInt(1000_000_000_000_000)), + }, + { + "extended denom - with fractional balance", + types.ExtendedCoinDenom, + sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(1000))), + sdkmath.NewInt(100), + // integer + fractional + sdk.NewCoin(types.ExtendedCoinDenom, sdk.NewInt(1000_000_000_000_100)), + }, + { + "extended denom - only fractional balance", + types.ExtendedCoinDenom, + // no coins in bank, only fractional balance + sdk.NewCoins(), + sdkmath.NewInt(100), + sdk.NewCoin(types.ExtendedCoinDenom, sdk.NewInt(100)), + }, + { + "extended denom - max fractional balance", + types.ExtendedCoinDenom, + sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(1000))), + types.ConversionFactor().SubRaw(1), + // integer + fractional + sdk.NewCoin(types.ExtendedCoinDenom, sdk.NewInt(1000_999_999_999_999)), + }, + { + "non-extended denom - ukava returns ukava", + types.IntegerCoinDenom, + sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(1000))), + sdk.ZeroInt(), + sdk.NewCoin("ukava", sdk.NewInt(1000)), + }, + { + "non-extended denom - unaffected by fractional balance", + "ukava", + sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1000))), + sdkmath.NewInt(100), + sdk.NewCoin("ukava", sdk.NewInt(1000)), + }, + { + "unrelated denom - no fractional", + "busd", + sdk.NewCoins(sdk.NewCoin("busd", sdk.NewInt(1000))), + sdk.ZeroInt(), + sdk.NewCoin("busd", sdk.NewInt(1000)), + }, + { + "unrelated denom - unaffected by fractional balance", + "busd", + sdk.NewCoins(sdk.NewCoin("busd", sdk.NewInt(1000))), + sdkmath.NewInt(100), + sdk.NewCoin("busd", sdk.NewInt(1000)), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tk := NewMockedTestData(t) + addr := sdk.AccAddress([]byte("test-address")) + + // Set fractional balance in store before query + tk.keeper.SetFractionalBalance(tk.ctx, addr, tt.giveFractionalBal) + + // Checks address if its a reserve denom + if tt.giveDenom == types.ExtendedCoinDenom { + tk.ak.EXPECT().GetModuleAddress(types.ModuleName). + Return(authtypes.NewModuleAddress(types.ModuleName)). + Once() + } + + if tt.giveDenom == types.ExtendedCoinDenom { + // No balance pass through + tk.bk.EXPECT(). + GetBalance(tk.ctx, addr, types.IntegerCoinDenom). + RunAndReturn(func(_ sdk.Context, _ sdk.AccAddress, _ string) sdk.Coin { + amt := tt.giveBankBal.AmountOf(types.IntegerCoinDenom) + return sdk.NewCoin(types.IntegerCoinDenom, amt) + }). + Once() + } else { + // Pass through to x/bank for denoms except ExtendedCoinDenom + tk.bk.EXPECT(). + GetBalance(tk.ctx, addr, tt.giveDenom). + RunAndReturn(func(ctx sdk.Context, aa sdk.AccAddress, s string) sdk.Coin { + require.Equal(t, s, tt.giveDenom, "unexpected denom passed to x/bank.GetBalance") + + return sdk.NewCoin(tt.giveDenom, tt.giveBankBal.AmountOf(s)) + }). + Once() + } + + bal := tk.keeper.GetBalance(tk.ctx, addr, tt.giveDenom) + require.Equal(t, tt.wantBal, bal) + }) + } +} + +func TestKeeper_SpendableCoin(t *testing.T) { + tests := []struct { + name string + giveDenom string // queried denom for balance + + giveBankBal sdk.Coins // mocked bank balance for giveAddr + giveFractionalBal sdkmath.Int // stored fractional balance for giveAddr + + wantBal sdk.Coin + }{ + { + "extended denom - no fractional balance", + types.ExtendedCoinDenom, + // queried bank balance in ukava when querying for akava + sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(1000))), + sdkmath.ZeroInt(), + // integer + fractional + sdk.NewCoin(types.ExtendedCoinDenom, sdk.NewInt(1000_000_000_000_000)), + }, + { + "extended denom - with fractional balance", + types.ExtendedCoinDenom, + sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(1000))), + sdkmath.NewInt(100), + // integer + fractional + sdk.NewCoin(types.ExtendedCoinDenom, sdk.NewInt(1000_000_000_000_100)), + }, + { + "extended denom - only fractional balance", + types.ExtendedCoinDenom, + // no coins in bank, only fractional balance + sdk.NewCoins(), + sdkmath.NewInt(100), + sdk.NewCoin(types.ExtendedCoinDenom, sdk.NewInt(100)), + }, + { + "extended denom - max fractional balance", + types.ExtendedCoinDenom, + sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(1000))), + types.ConversionFactor().SubRaw(1), + // integer + fractional + sdk.NewCoin(types.ExtendedCoinDenom, sdk.NewInt(1000_999_999_999_999)), + }, + { + "non-extended denom - ukava returns ukava", + types.IntegerCoinDenom, + sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(1000))), + sdk.ZeroInt(), + sdk.NewCoin("ukava", sdk.NewInt(1000)), + }, + { + "non-extended denom - unaffected by fractional balance", + "ukava", + sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1000))), + sdkmath.NewInt(100), + sdk.NewCoin("ukava", sdk.NewInt(1000)), + }, + { + "unrelated denom - no fractional", + "busd", + sdk.NewCoins(sdk.NewCoin("busd", sdk.NewInt(1000))), + sdk.ZeroInt(), + sdk.NewCoin("busd", sdk.NewInt(1000)), + }, + { + "unrelated denom - unaffected by fractional balance", + "busd", + sdk.NewCoins(sdk.NewCoin("busd", sdk.NewInt(1000))), + sdkmath.NewInt(100), + sdk.NewCoin("busd", sdk.NewInt(1000)), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tk := NewMockedTestData(t) + addr := sdk.AccAddress([]byte("test-address")) + + // Set fractional balance in store before query + tk.keeper.SetFractionalBalance(tk.ctx, addr, tt.giveFractionalBal) + + // If its a reserve denom, module address is checked + if tt.giveDenom == types.ExtendedCoinDenom { + tk.ak.EXPECT().GetModuleAddress(types.ModuleName). + Return(authtypes.NewModuleAddress(types.ModuleName)). + Once() + } + + if tt.giveDenom == types.ExtendedCoinDenom { + // No balance pass through + tk.bk.EXPECT(). + SpendableCoin(tk.ctx, addr, types.IntegerCoinDenom). + RunAndReturn(func(_ sdk.Context, _ sdk.AccAddress, _ string) sdk.Coin { + amt := tt.giveBankBal.AmountOf(types.IntegerCoinDenom) + return sdk.NewCoin(types.IntegerCoinDenom, amt) + }). + Once() + } else { + // Pass through to x/bank for denoms except ExtendedCoinDenom + tk.bk.EXPECT(). + SpendableCoin(tk.ctx, addr, tt.giveDenom). + RunAndReturn(func(ctx sdk.Context, aa sdk.AccAddress, s string) sdk.Coin { + require.Equal(t, s, tt.giveDenom, "unexpected denom passed to x/bank.GetBalance") + + return sdk.NewCoin(tt.giveDenom, tt.giveBankBal.AmountOf(s)) + }). + Once() + } + + bal := tk.keeper.SpendableCoin(tk.ctx, addr, tt.giveDenom) + require.Equal(t, tt.wantBal, bal) + }) + } +} + +func TestHiddenReserve(t *testing.T) { + // Reserve balances should not be shown to consumers of x/precisebank, as it + // represents the fractional balances of accounts. + + tk := NewMockedTestData(t) + + moduleAddr := authtypes.NewModuleAddress(types.ModuleName) + + // No mock bankkeeper expectations, which means the zero coin is returned + // directly for reserve address. So the mock bankkeeper doesn't need to have + // a handler for getting underlying balance. + + tests := []struct { + name string + denom string + expectedBalance sdk.Coin + }{ + {"akava", types.ExtendedCoinDenom, sdk.NewCoin(types.ExtendedCoinDenom, sdkmath.ZeroInt())}, + {"ukava", types.IntegerCoinDenom, sdk.NewCoin(types.IntegerCoinDenom, sdkmath.NewInt(1))}, + {"unrelated denom", "cat", sdk.NewCoin("cat", sdkmath.ZeroInt())}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // 2 calls for GetBalance and SpendableCoin, only for reserve coins + if tt.denom == "akava" { + tk.ak.EXPECT().GetModuleAddress(types.ModuleName). + Return(moduleAddr). + Twice() + } else { + // Passthrough to x/bank for non-reserve denoms + tk.bk.EXPECT(). + GetBalance(tk.ctx, moduleAddr, tt.denom). + Return(sdk.NewCoin(tt.denom, sdkmath.ZeroInt())). + Once() + + tk.bk.EXPECT(). + SpendableCoin(tk.ctx, moduleAddr, tt.denom). + Return(sdk.NewCoin(tt.denom, sdkmath.ZeroInt())). + Once() + } + + // GetBalance should return zero balance for reserve address + coin := tk.keeper.GetBalance(tk.ctx, moduleAddr, tt.denom) + require.Equal(t, tt.denom, coin.Denom) + require.Equal(t, sdkmath.ZeroInt(), coin.Amount) + + // SpendableCoin should return zero balance for reserve address + spendableCoin := tk.keeper.SpendableCoin(tk.ctx, moduleAddr, tt.denom) + require.Equal(t, tt.denom, spendableCoin.Denom) + require.Equal(t, sdkmath.ZeroInt(), spendableCoin.Amount) + }) + } +} diff --git a/x/precisebank/module.go b/x/precisebank/module.go new file mode 100644 index 00000000..f81c39c0 --- /dev/null +++ b/x/precisebank/module.go @@ -0,0 +1,159 @@ +package precisebank + +import ( + "context" + "encoding/json" + + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/spf13/cobra" + + abci "github.com/cometbft/cometbft/abci/types" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + cdctypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + + "github.com/0glabs/0g-chain/x/precisebank/keeper" + "github.com/0glabs/0g-chain/x/precisebank/types" +) + +// ConsensusVersion defines the current module consensus version. +const ConsensusVersion = 1 + +var ( + _ module.AppModule = AppModule{} + _ module.AppModuleBasic = AppModuleBasic{} +) + +// ---------------------------------------------------------------------------- +// AppModuleBasic +// ---------------------------------------------------------------------------- + +// AppModuleBasic app module basics object +type AppModuleBasic struct{} + +func NewAppModuleBasic() AppModuleBasic { + return AppModuleBasic{} +} + +// Name get module name +func (AppModuleBasic) Name() string { + return types.ModuleName +} + +// Registers legacy amino codec +func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + types.RegisterLegacyAminoCodec(cdc) +} + +// RegisterInterfaces registers the module's interface types +func (a AppModuleBasic) RegisterInterfaces(reg cdctypes.InterfaceRegistry) { + types.RegisterInterfaces(reg) +} + +// DefaultGenesis default genesis state +func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { + gs := types.DefaultGenesisState() + return cdc.MustMarshalJSON(gs) +} + +// ValidateGenesis module validate genesis +func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncodingConfig, bz json.RawMessage) error { + var gs types.GenesisState + err := cdc.UnmarshalJSON(bz, &gs) + if err != nil { + return err + } + return gs.Validate() +} + +// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for precisebank module. +func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) { + if err := types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)); err != nil { + panic(err) + } +} + +// GetTxCmd returns precisebank module's root tx command. +func (a AppModuleBasic) GetTxCmd() *cobra.Command { + return nil +} + +// GetQueryCmd returns precisebank module's root query command. +func (AppModuleBasic) GetQueryCmd() *cobra.Command { + return nil +} + +// ---------------------------------------------------------------------------- +// AppModule +// ---------------------------------------------------------------------------- + +// AppModule implements the AppModule interface for precisebank module. +type AppModule struct { + AppModuleBasic + + keeper keeper.Keeper + accountKeeper types.AccountKeeper + bankKeeper types.BankKeeper +} + +// NewAppModule creates a new AppModule object +func NewAppModule( + keeper keeper.Keeper, + bankKeeper types.BankKeeper, + accountKeeper types.AccountKeeper, +) AppModule { + return AppModule{ + AppModuleBasic: NewAppModuleBasic(), + keeper: keeper, + accountKeeper: accountKeeper, + bankKeeper: bankKeeper, + } +} + +// Name returns precisebank module's name. +func (am AppModule) Name() string { + return am.AppModuleBasic.Name() +} + +// RegisterServices registers a GRPC query service to respond to the +// module-specific GRPC queries. +func (am AppModule) RegisterServices(cfg module.Configurator) { + types.RegisterQueryServer(cfg.QueryServer(), keeper.NewQueryServerImpl(am.keeper)) +} + +// RegisterInvariants registers precisebank module's invariants. +func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) { + keeper.RegisterInvariants(ir, am.keeper, am.bankKeeper) +} + +// InitGenesis performs precisebank module's genesis initialization It returns +// no validator updates. +func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, gs json.RawMessage) []abci.ValidatorUpdate { + var genState types.GenesisState + // Initialize global index to index in genesis state + cdc.MustUnmarshalJSON(gs, &genState) + + InitGenesis(ctx, am.keeper, am.accountKeeper, am.bankKeeper, &genState) + return []abci.ValidatorUpdate{} +} + +// ExportGenesis returns precisebank module's exported genesis state as raw JSON bytes. +func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage { + gs := ExportGenesis(ctx, am.keeper) + return cdc.MustMarshalJSON(gs) +} + +// ConsensusVersion implements ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { return ConsensusVersion } + +// BeginBlock executes all ABCI BeginBlock logic respective to precisebank module. +func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) {} + +// EndBlock executes all ABCI EndBlock logic respective to precisebank module. It +// returns no validator updates. +func (am AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { + return []abci.ValidatorUpdate{} +} diff --git a/x/precisebank/testutil/fractional_balances.go b/x/precisebank/testutil/fractional_balances.go new file mode 100644 index 00000000..7e3b4039 --- /dev/null +++ b/x/precisebank/testutil/fractional_balances.go @@ -0,0 +1,155 @@ +package testutil + +import ( + crand "crypto/rand" + "math/rand" + "testing" + + sdkmath "cosmossdk.io/math" + "github.com/0glabs/0g-chain/x/precisebank/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" + "github.com/stretchr/testify/require" +) + +// randRange returns a random number in the range [min, max) +// meaning max is never returned +func randRange(min, max int64) int64 { + return rand.Int63n(max-min) + min +} + +func randAccAddress() sdk.AccAddress { + addrBytes := make([]byte, address.MaxAddrLen) + _, err := crand.Read(addrBytes) + if err != nil { + panic(err) + } + + addr := sdk.AccAddress(addrBytes) + if addr.Empty() { + panic("empty address") + } + + return addr +} + +// GenerateEqualFractionalBalances generates count number of FractionalBalances +// with randomly generated amounts such that the sum of all amounts is a +// multiple of types.CONVERSION_FACTOR. If a remainder is desired, any single +// FractionalBalance can be removed from the returned slice and used as the +// remainder. +func GenerateEqualFractionalBalances( + t *testing.T, + count int, +) types.FractionalBalances { + t.Helper() + + // 1 account is not valid, as the total amount needs to be a multiple of + // conversionFactor. 0 < account balance < conversionFactor, so there must + // be at least 2 + // NOTE: THIS IS ONLY TRUE WITH 0 REMAINDER + // GenerateEqualFractionalBalancesWithRemainder repurposes the last balance + // as the remainder, so this >= 2 requirement is not true in production code. + require.GreaterOrEqual(t, count, 2, "count must be at least 2 to generate balances") + + fbs := make(types.FractionalBalances, count) + sum := sdkmath.ZeroInt() + + // Random amounts for count - 1 FractionalBalances + for i := 0; i < count-1; i++ { + // Not just using sdk.AccAddress{byte(count)} since that has limited + // range + addr := randAccAddress().String() + + // Random 1 < amt < ConversionFactor + // POSITIVE and less than ConversionFactor + // If it's 0, Validate() will error. + // Why start at 2 instead of 1? We want to make sure its divisible + // for the last account, more details below. + amt := randRange(2, types.ConversionFactor().Int64()) + amtInt := sdkmath.NewInt(amt) + + fb := types.NewFractionalBalance(addr, amtInt) + require.NoError(t, fb.Validate()) + + fbs[i] = fb + + sum = sum.Add(amtInt) + } + + // Last FractionalBalance must make sum of all balances equal to have 0 + // fractional remainder. Effectively the amount needed to round up to the + // nearest integer amount to make this true. + // (sum + lastAmt) % CONVERSION_FACTOR = 0 + // aka + // CONVERSION_FACTOR - (sum % CONVERSION_FACTOR) = lastAmt + addr := randAccAddress().String() + + // Why do we need to Mod(conversionFactor) again? + // Edge case without: If sum == ConversionFactor, then lastAmt == 0 not ConversionFactor + // 1_000_000_000_000 - (1_000_000_000_000 % 1_000_000_000_000) + // = 1_000_000_000_000 - 0 + // = 1_000_000_000_000 (invalid!) + + // Note that we only have this issue in tests since we want to calculate a + // new valid remainder, but we only validate in the actual code. + amt := types.ConversionFactor(). + Sub(sum.Mod(types.ConversionFactor())). + Mod(types.ConversionFactor()) + + // We only want to generate VALID FractionalBalances - zero would not be + // valid, so let's just borrow half of the previous amount. We generated + // amounts from 2 to ConversionFactor, so we know the previous amount is + // at least 2 and thus able to be split into two valid balances. + if amt.IsZero() { + fbs[count-2].Amount = fbs[count-2].Amount.QuoRaw(2) + amt = fbs[count-2].Amount + } + + fb := types.NewFractionalBalance(addr, amt) + require.NoError(t, fb.Validate()) + + fbs[count-1] = fb + + // Lets double check this before returning + verificationSum := sdkmath.ZeroInt() + for _, fb := range fbs { + verificationSum = verificationSum.Add(fb.Amount) + } + require.True(t, verificationSum.Mod(types.ConversionFactor()).IsZero()) + + // Also make sure no duplicate addresses + require.NoError(t, fbs.Validate()) + + return fbs +} + +// GenerateEqualFractionalBalancesWithRemainder generates count number of +// FractionalBalances with randomly generated amounts as well as a non-zero +// remainder. +// 0 == (sum(FractionalBalances) + remainder) % conversionFactor +// Where remainder > 0 +func GenerateEqualFractionalBalancesWithRemainder( + t *testing.T, + count int, +) (types.FractionalBalances, sdkmath.Int) { + t.Helper() + + require.GreaterOrEqual(t, count, 2, "count must be at least 2 to generate both balances and remainder") + + countWithRemainder := count + 1 + + // Generate 1 additional FractionalBalance so we can use one as remainder + fbs := GenerateEqualFractionalBalances(t, countWithRemainder) + + // Use the last one as remainder + remainder := fbs[countWithRemainder-1].Amount + + // Remove the balance used as remainder from the slice + fbs = fbs[:countWithRemainder-1] + + require.Len(t, fbs, count) + require.NotZero(t, remainder.Int64(), "remainder must be non-zero") + + return fbs, remainder +} diff --git a/x/precisebank/testutil/suite.go b/x/precisebank/testutil/suite.go new file mode 100644 index 00000000..70fd35f9 --- /dev/null +++ b/x/precisebank/testutil/suite.go @@ -0,0 +1,151 @@ +package testutil + +import ( + "time" + + abci "github.com/cometbft/cometbft/abci/types" + "github.com/cometbft/cometbft/crypto/tmhash" + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + tmversion "github.com/cometbft/cometbft/proto/tendermint/version" + tmtime "github.com/cometbft/cometbft/types/time" + "github.com/cometbft/cometbft/version" + sdk "github.com/cosmos/cosmos-sdk/types" + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + "github.com/evmos/ethermint/crypto/ethsecp256k1" + "github.com/stretchr/testify/suite" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/precisebank/keeper" + "github.com/0glabs/0g-chain/x/precisebank/types" +) + +type Suite struct { + suite.Suite + + App app.TestApp + Ctx sdk.Context + BankKeeper bankkeeper.Keeper + AccountKeeper authkeeper.AccountKeeper + Keeper keeper.Keeper +} + +func (suite *Suite) SetupTest() { + tApp := app.NewTestApp() + + suite.Ctx = tApp.NewContext(true, tmproto.Header{Height: 1, Time: tmtime.Now()}) + suite.App = tApp + suite.BankKeeper = tApp.GetBankKeeper() + suite.AccountKeeper = tApp.GetAccountKeeper() + suite.Keeper = tApp.GetPrecisebankKeeper() + + cdc := suite.App.AppCodec() + coins := sdk.NewCoins(sdk.NewInt64Coin("ua0gi", 1000_000_000_000_000_000)) + authGS := app.NewFundedGenStateWithSameCoins(cdc, coins, []sdk.AccAddress{}) + + gs := app.GenesisState{} + suite.App.InitializeFromGenesisStates(authGS, gs) + + // consensus key - needed to set up evm module + consPriv, err := ethsecp256k1.GenerateKey() + suite.Require().NoError(err) + consAddress := sdk.ConsAddress(consPriv.PubKey().Address()) + + // InitializeFromGenesisStates commits first block so we start at 2 here + suite.Ctx = suite.App.NewContext(false, tmproto.Header{ + Height: suite.App.LastBlockHeight() + 1, + ChainID: app.TestChainId, + Time: time.Now().UTC(), + ProposerAddress: consAddress.Bytes(), + Version: tmversion.Consensus{ + Block: version.BlockProtocol, + }, + LastBlockId: tmproto.BlockID{ + Hash: tmhash.Sum([]byte("block_id")), + PartSetHeader: tmproto.PartSetHeader{ + Total: 11, + Hash: tmhash.Sum([]byte("partset_header")), + }, + }, + AppHash: tmhash.Sum([]byte("app")), + DataHash: tmhash.Sum([]byte("data")), + EvidenceHash: tmhash.Sum([]byte("evidence")), + ValidatorsHash: tmhash.Sum([]byte("validators")), + NextValidatorsHash: tmhash.Sum([]byte("next_validators")), + ConsensusHash: tmhash.Sum([]byte("consensus")), + LastResultsHash: tmhash.Sum([]byte("last_result")), + }) +} + +func (suite *Suite) Commit() { + _ = suite.App.Commit() + header := suite.Ctx.BlockHeader() + header.Height += 1 + suite.App.BeginBlock(abci.RequestBeginBlock{ + Header: header, + }) + + // update ctx + suite.Ctx = suite.App.NewContext(false, header) +} + +// MintToAccount mints coins to an account with the x/precisebank methods. This +// must be used when minting extended coins, ie. akava coins. This depends on +// the methods to be properly tested to be implemented correctly. +func (suite *Suite) MintToAccount(addr sdk.AccAddress, amt sdk.Coins) { + accBalancesBefore := suite.GetAllBalances(addr) + + err := suite.Keeper.MintCoins(suite.Ctx, minttypes.ModuleName, amt) + suite.Require().NoError(err) + + err = suite.Keeper.SendCoinsFromModuleToAccount(suite.Ctx, minttypes.ModuleName, addr, amt) + suite.Require().NoError(err) + + // Double check balances are correctly minted and sent to account + accBalancesAfter := suite.GetAllBalances(addr) + + netIncrease := accBalancesAfter.Sub(accBalancesBefore...) + suite.Require().Equal(ConvertCoinsToExtendedCoinDenom(amt), netIncrease) + + suite.T().Logf("minted %s to %s", amt, addr) +} + +// GetAllBalances returns all the account balances for the given account address. +// This returns the extended coin balance if the account has a non-zero balance, +// WITHOUT the integer coin balance. +func (suite *Suite) GetAllBalances(addr sdk.AccAddress) sdk.Coins { + // Get all balances for an account + bankBalances := suite.BankKeeper.GetAllBalances(suite.Ctx, addr) + + // Remove integer coins from the balance + for _, coin := range bankBalances { + if coin.Denom == types.IntegerCoinDenom { + bankBalances = bankBalances.Sub(coin) + } + } + + // Replace the integer coin with the extended coin, from x/precisebank + extendedBal := suite.Keeper.GetBalance(suite.Ctx, addr, types.ExtendedCoinDenom) + + return bankBalances.Add(extendedBal) +} + +// ConvertCoinsToExtendedCoinDenom converts sdk.Coins that includes Integer denoms +// to sdk.Coins that includes Extended denoms of the same amount. This is useful +// for testing to make sure only extended amounts are compared instead of double +// counting balances. +func ConvertCoinsToExtendedCoinDenom(coins sdk.Coins) sdk.Coins { + integerCoinAmt := coins.AmountOf(types.IntegerCoinDenom) + if integerCoinAmt.IsZero() { + return coins + } + + // Remove the integer coin from the coins + integerCoin := sdk.NewCoin(types.IntegerCoinDenom, integerCoinAmt) + + // Add the equivalent extended coin to the coins + extendedCoin := sdk.NewCoin(types.ExtendedCoinDenom, integerCoinAmt.Mul(types.ConversionFactor())) + + return coins.Sub(integerCoin).Add(extendedCoin) +} diff --git a/x/precisebank/types/codec.go b/x/precisebank/types/codec.go new file mode 100644 index 00000000..772fa40e --- /dev/null +++ b/x/precisebank/types/codec.go @@ -0,0 +1,33 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec" + cdctypes "github.com/cosmos/cosmos-sdk/codec/types" + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" +) + +// RegisterLegacyAminoCodec registers the necessary evmutil interfaces and concrete types +// on the provided LegacyAmino codec. These types are used for Amino JSON serialization. +func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { +} + +func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { + registry.RegisterImplementations((*sdk.Msg)(nil)) +} + +var ( + amino = codec.NewLegacyAmino() + ModuleCdc = codec.NewAminoCodec(amino) +) + +func init() { + RegisterLegacyAminoCodec(amino) + cryptocodec.RegisterCrypto(amino) + amino.Seal() + + // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be + // used to properly serialize MsgGrant and MsgExec instances + RegisterLegacyAminoCodec(authzcodec.Amino) +} diff --git a/x/precisebank/types/constants.go b/x/precisebank/types/constants.go new file mode 100644 index 00000000..2f7bf7a3 --- /dev/null +++ b/x/precisebank/types/constants.go @@ -0,0 +1,11 @@ +package types + +// IntegerCoinDenom is the denomination for integer coins that are managed by +// x/bank. This is the "true" denomination of the coin, and is also used for +// the reserve to back all fractional coins. +const IntegerCoinDenom = "ua0gi" + +// ExtendedCoinDenom is the denomination for the extended IntegerCoinDenom. This +// not only represents the fractional balance, but the total balance of +// integer + fractional balances. +const ExtendedCoinDenom = "neuron" diff --git a/x/precisebank/types/expected_keepers.go b/x/precisebank/types/expected_keepers.go new file mode 100644 index 00000000..e80741f1 --- /dev/null +++ b/x/precisebank/types/expected_keepers.go @@ -0,0 +1,31 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +// AccountKeeper defines the expected account keeper interface +type AccountKeeper interface { + GetModuleAccount(ctx sdk.Context, moduleName string) authtypes.ModuleAccountI + GetModuleAddress(moduleName string) sdk.AccAddress + GetSequence(sdk.Context, sdk.AccAddress) (uint64, error) +} + +// BankKeeper defines the expected bank keeper interface +type BankKeeper interface { + IsSendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error + GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin + GetSupply(ctx sdk.Context, denom string) sdk.Coin + SpendableCoin(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin + + BlockedAddr(addr sdk.AccAddress) bool + + SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error + SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error + SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error + SendCoinsFromModuleToModule(ctx sdk.Context, senderModule string, recipientModule string, amt sdk.Coins) error + + MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error + BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error +} diff --git a/x/precisebank/types/extended_balance.go b/x/precisebank/types/extended_balance.go new file mode 100644 index 00000000..d4f674db --- /dev/null +++ b/x/precisebank/types/extended_balance.go @@ -0,0 +1,25 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// SumExtendedCoin returns a sdk.Coin of extended coin denomination +// with all integer and fractional amounts combined. e.g. if amount contains +// both coins of integer denom and extended denom, this will return the total +// amount in extended coins. This is intended to get the full value to emit in +// events. +func SumExtendedCoin(amt sdk.Coins) sdk.Coin { + // ukava converted to akava + integerAmount := amt.AmountOf(IntegerCoinDenom).Mul(conversionFactor) + // akava as is + extendedAmount := amt.AmountOf(ExtendedCoinDenom) + + // total of ukava and akava amounts + fullEmissionAmount := integerAmount.Add(extendedAmount) + + return sdk.NewCoin( + ExtendedCoinDenom, + fullEmissionAmount, + ) +} diff --git a/x/precisebank/types/extended_balance_test.go b/x/precisebank/types/extended_balance_test.go new file mode 100644 index 00000000..6686e5fe --- /dev/null +++ b/x/precisebank/types/extended_balance_test.go @@ -0,0 +1,48 @@ +package types_test + +import ( + "testing" + + "github.com/0glabs/0g-chain/x/precisebank/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +func TestSumExtendedCoin(t *testing.T) { + tests := []struct { + name string + amt sdk.Coins + want sdk.Coin + }{ + { + "empty", + sdk.NewCoins(), + sdk.NewCoin(types.ExtendedCoinDenom, sdk.ZeroInt()), + }, + { + "only integer", + sdk.NewCoins(sdk.NewInt64Coin(types.IntegerCoinDenom, 100)), + sdk.NewCoin(types.ExtendedCoinDenom, types.ConversionFactor().MulRaw(100)), + }, + { + "only extended", + sdk.NewCoins(sdk.NewInt64Coin(types.ExtendedCoinDenom, 100)), + sdk.NewCoin(types.ExtendedCoinDenom, sdk.NewInt(100)), + }, + { + "integer and extended", + sdk.NewCoins( + sdk.NewInt64Coin(types.IntegerCoinDenom, 100), + sdk.NewInt64Coin(types.ExtendedCoinDenom, 100), + ), + sdk.NewCoin(types.ExtendedCoinDenom, types.ConversionFactor().MulRaw(100).AddRaw(100)), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + extVal := types.SumExtendedCoin(tt.amt) + require.Equal(t, tt.want, extVal) + }) + } +} diff --git a/x/precisebank/types/fractional_balance.go b/x/precisebank/types/fractional_balance.go new file mode 100644 index 00000000..33d02c0d --- /dev/null +++ b/x/precisebank/types/fractional_balance.go @@ -0,0 +1,59 @@ +package types + +import ( + fmt "fmt" + + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// conversionFactor is used to convert the fractional balance to integer +// balances. +var conversionFactor = sdkmath.NewInt(1_000_000_000_000) + +// ConversionFactor returns a copy of the conversionFactor used to convert the +// fractional balance to integer balances. This is also 1 greater than the max +// valid fractional amount (999_999_999_999): +// 0 < FractionalBalance < conversionFactor +func ConversionFactor() sdkmath.Int { + return sdkmath.NewIntFromBigIntMut(conversionFactor.BigInt()) +} + +// FractionalBalance returns a new FractionalBalance with the given address and +// amount. +func NewFractionalBalance(address string, amount sdkmath.Int) FractionalBalance { + return FractionalBalance{ + Address: address, + Amount: amount, + } +} + +// Validate returns an error if the FractionalBalance has an invalid address or +// negative amount. +func (fb FractionalBalance) Validate() error { + if _, err := sdk.AccAddressFromBech32(fb.Address); err != nil { + return err + } + + // Validate the amount with the FractionalAmount wrapper + return ValidateFractionalAmount(fb.Amount) +} + +// ValidateFractionalAmount checks if an sdkmath.Int is a valid fractional +// amount, ensuring it is positive and less than or equal to the maximum +// fractional amount. +func ValidateFractionalAmount(amt sdkmath.Int) error { + if amt.IsNil() { + return fmt.Errorf("nil amount") + } + + if !amt.IsPositive() { + return fmt.Errorf("non-positive amount %v", amt) + } + + if amt.GTE(conversionFactor) { + return fmt.Errorf("amount %v exceeds max of %v", amt, conversionFactor.SubRaw(1)) + } + + return nil +} diff --git a/x/precisebank/types/fractional_balance_test.go b/x/precisebank/types/fractional_balance_test.go new file mode 100644 index 00000000..2bb822e4 --- /dev/null +++ b/x/precisebank/types/fractional_balance_test.go @@ -0,0 +1,173 @@ +package types_test + +import ( + "math/big" + "testing" + + sdkmath "cosmossdk.io/math" + "github.com/0glabs/0g-chain/chaincfg" + "github.com/0glabs/0g-chain/x/precisebank/types" + "github.com/stretchr/testify/require" +) + +func TestConversionFactor_Immutable(t *testing.T) { + cf1 := types.ConversionFactor() + origInt64 := cf1.Int64() + + // Get the internal pointer to the big.Int without copying + internalBigInt := cf1.BigIntMut() + + // Mutate the big.Int -- .Add() mutates in place + internalBigInt.Add(internalBigInt, big.NewInt(5)) + // Ensure bigInt was actually mutated + require.Equal(t, origInt64+5, internalBigInt.Int64()) + + // Fetch the max amount again + cf2 := types.ConversionFactor() + + require.Equal( + t, + origInt64, + cf2.Int64(), + "conversion factor should be immutable", + ) +} + +func TestConversionFactor_Copied(t *testing.T) { + max1 := types.ConversionFactor().BigIntMut() + max2 := types.ConversionFactor().BigIntMut() + + // Checks that the returned two pointers do not reference the same object + require.NotSame(t, max1, max2, "max fractional amount should be copied") +} + +func TestConversionFactor(t *testing.T) { + require.Equal( + t, + sdkmath.NewInt(1_000_000_000_000), + types.ConversionFactor(), + "conversion factor should have 12 decimal points", + ) +} + +func TestNewFractionalBalance(t *testing.T) { + tests := []struct { + name string + giveAddress string + giveAmount sdkmath.Int + }{ + { + "correctly sets fields", + "cosmos1qperwt9wrnkg5k9e5gzfgjppzpqur82k6c5a0n", + sdkmath.NewInt(100), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + fb := types.NewFractionalBalance(tt.giveAddress, tt.giveAmount) + + require.Equal(t, tt.giveAddress, fb.Address) + require.Equal(t, tt.giveAmount, fb.Amount) + }) + } +} + +func TestFractionalBalance_Validate(t *testing.T) { + chaincfg.SetSDKConfig() + + tests := []struct { + name string + giveAddress string + giveAmount sdkmath.Int + wantErr string + }{ + { + "valid", + "kava1gpxd677pp8zr97xvy3pmgk70a9vcpagsakv0tx", + sdkmath.NewInt(100), + "", + }, + { + "valid - uppercase address", + "KAVA1GPXD677PP8ZR97XVY3PMGK70A9VCPAGSAKV0TX", + sdkmath.NewInt(100), + "", + }, + { + "valid - min balance", + "kava1gpxd677pp8zr97xvy3pmgk70a9vcpagsakv0tx", + sdkmath.NewInt(1), + "", + }, + { + "valid - max balance", + "kava1gpxd677pp8zr97xvy3pmgk70a9vcpagsakv0tx", + types.ConversionFactor().SubRaw(1), + "", + }, + { + "invalid - 0 balance", + "kava1gpxd677pp8zr97xvy3pmgk70a9vcpagsakv0tx", + sdkmath.NewInt(0), + "non-positive amount 0", + }, + { + "invalid - empty", + "kava1gpxd677pp8zr97xvy3pmgk70a9vcpagsakv0tx", + sdkmath.Int{}, + "nil amount", + }, + { + "invalid - mixed case address", + "kava1gpxd677pP8zr97xvy3pmgk70a9vcpagsakv0tx", + sdkmath.NewInt(100), + "decoding bech32 failed: string not all lowercase or all uppercase", + }, + { + "invalid - non-bech32 address", + "invalid", + sdkmath.NewInt(100), + "decoding bech32 failed: invalid bech32 string length 7", + }, + { + "invalid - wrong bech32 prefix", + "cosmos1qperwt9wrnkg5k9e5gzfgjppzpqur82k7gqd8n", + sdkmath.NewInt(100), + "invalid Bech32 prefix; expected kava, got cosmos", + }, + { + "invalid - negative amount", + "kava1gpxd677pp8zr97xvy3pmgk70a9vcpagsakv0tx", + sdkmath.NewInt(-100), + "non-positive amount -100", + }, + { + "invalid - max amount + 1", + "kava1gpxd677pp8zr97xvy3pmgk70a9vcpagsakv0tx", + types.ConversionFactor(), + "amount 1000000000000 exceeds max of 999999999999", + }, + { + "invalid - much more than max amount", + "kava1gpxd677pp8zr97xvy3pmgk70a9vcpagsakv0tx", + sdkmath.NewInt(100000000000_000), + "amount 100000000000000 exceeds max of 999999999999", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + fb := types.NewFractionalBalance(tt.giveAddress, tt.giveAmount) + err := fb.Validate() + + if tt.wantErr == "" { + require.NoError(t, err) + return + } + + require.Error(t, err) + require.EqualError(t, err, tt.wantErr) + }) + } +} diff --git a/x/precisebank/types/fractional_balances.go b/x/precisebank/types/fractional_balances.go new file mode 100644 index 00000000..656e47b3 --- /dev/null +++ b/x/precisebank/types/fractional_balances.go @@ -0,0 +1,48 @@ +package types + +import ( + fmt "fmt" + "strings" + + sdkmath "cosmossdk.io/math" +) + +// FractionalBalances is a slice of FractionalBalance +type FractionalBalances []FractionalBalance + +// Validate returns an error if any FractionalBalance in the slice is invalid. +func (fbs FractionalBalances) Validate() error { + seenAddresses := make(map[string]struct{}) + + for _, fb := range fbs { + // Individual FractionalBalance validation + if err := fb.Validate(); err != nil { + return fmt.Errorf("invalid fractional balance for %s: %w", fb.Address, err) + } + + // Make addresses all lowercase for unique check, as ALL UPPER is also + // a valid address. + lowerAddr := strings.ToLower(fb.Address) + + // If this is a duplicate address, return an error + if _, found := seenAddresses[lowerAddr]; found { + return fmt.Errorf("duplicate address %v", lowerAddr) + } + + // Mark it as seen + seenAddresses[lowerAddr] = struct{}{} + } + + return nil +} + +// SumAmount returns the sum of all the amounts in the slice. +func (fbs FractionalBalances) SumAmount() sdkmath.Int { + sum := sdkmath.ZeroInt() + + for _, fb := range fbs { + sum = sum.Add(fb.Amount) + } + + return sum +} diff --git a/x/precisebank/types/fractional_balances_test.go b/x/precisebank/types/fractional_balances_test.go new file mode 100644 index 00000000..869e4e60 --- /dev/null +++ b/x/precisebank/types/fractional_balances_test.go @@ -0,0 +1,159 @@ +package types_test + +import ( + "math/big" + "math/rand" + "strings" + "testing" + + sdkmath "cosmossdk.io/math" + "github.com/0glabs/0g-chain/chaincfg" + "github.com/0glabs/0g-chain/x/precisebank/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +func TestFractionalBalances_Validate(t *testing.T) { + chaincfg.SetSDKConfig() + + tests := []struct { + name string + fbs types.FractionalBalances + wantErr string + }{ + { + "valid - empty", + types.FractionalBalances{}, + "", + }, + { + "valid - nil", + nil, + "", + }, + { + "valid - multiple balances", + types.FractionalBalances{ + types.NewFractionalBalance(sdk.AccAddress{1}.String(), sdkmath.NewInt(100)), + types.NewFractionalBalance(sdk.AccAddress{2}.String(), sdkmath.NewInt(100)), + types.NewFractionalBalance(sdk.AccAddress{3}.String(), sdkmath.NewInt(100)), + }, + "", + }, + { + "invalid - single invalid balance", + types.FractionalBalances{ + types.NewFractionalBalance(sdk.AccAddress{1}.String(), sdkmath.NewInt(100)), + types.NewFractionalBalance(sdk.AccAddress{2}.String(), sdkmath.NewInt(-1)), + types.NewFractionalBalance(sdk.AccAddress{3}.String(), sdkmath.NewInt(100)), + }, + "invalid fractional balance for kava1qg7c45n6: non-positive amount -1", + }, + { + "invalid - duplicate address", + types.FractionalBalances{ + types.NewFractionalBalance(sdk.AccAddress{1}.String(), sdkmath.NewInt(100)), + types.NewFractionalBalance(sdk.AccAddress{1}.String(), sdkmath.NewInt(100)), + }, + "duplicate address kava1qy0xn7za", + }, + { + "invalid - duplicate address upper/lower case", + types.FractionalBalances{ + types.NewFractionalBalance( + strings.ToLower(sdk.AccAddress{1}.String()), + sdkmath.NewInt(100), + ), + types.NewFractionalBalance( + strings.ToUpper(sdk.AccAddress{1}.String()), + sdkmath.NewInt(100), + ), + }, + "duplicate address kava1qy0xn7za", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := tt.fbs.Validate() + if tt.wantErr == "" { + require.NoError(t, err) + return + } + + require.Error(t, err) + require.EqualError(t, err, tt.wantErr) + }) + } +} + +func TestFractionalBalances_SumAmount(t *testing.T) { + generateRandomFractionalBalances := func(n int) (types.FractionalBalances, sdkmath.Int) { + balances := make(types.FractionalBalances, n) + sum := sdkmath.ZeroInt() + + for i := 0; i < n; i++ { + addr := sdk.AccAddress{byte(i)}.String() + amount := sdkmath.NewInt(rand.Int63()) + balances[i] = types.NewFractionalBalance(addr, amount) + + sum = sum.Add(amount) + } + + return balances, sum + } + + multiBalances, sum := generateRandomFractionalBalances(10) + + tests := []struct { + name string + balances types.FractionalBalances + wantSum sdkmath.Int + }{ + { + "empty", + types.FractionalBalances{}, + sdkmath.ZeroInt(), + }, + { + "single", + types.FractionalBalances{ + types.NewFractionalBalance(sdk.AccAddress{1}.String(), sdkmath.NewInt(100)), + }, + sdkmath.NewInt(100), + }, + { + "multiple", + multiBalances, + sum, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + sum := tt.balances.SumAmount() + require.Equal(t, tt.wantSum, sum) + }) + } +} + +func TestFractionalBalances_SumAmount_Overflow(t *testing.T) { + // 2^256 - 1 + maxInt := new(big.Int).Sub( + new(big.Int).Exp(big.NewInt(2), big.NewInt(256), nil), + big.NewInt(1), + ) + + fbs := types.FractionalBalances{ + types.NewFractionalBalance(sdk.AccAddress{1}.String(), sdkmath.NewInt(100)), + // This is NOT valid, but just to test overflows will panic + types.NewFractionalBalance( + sdk.AccAddress{2}.String(), + sdkmath.NewIntFromBigInt(maxInt), + ), + } + + require.PanicsWithError(t, sdkmath.ErrIntOverflow.Error(), func() { + _ = fbs.SumAmount() + }) +} diff --git a/x/precisebank/types/genesis.go b/x/precisebank/types/genesis.go new file mode 100644 index 00000000..38587b25 --- /dev/null +++ b/x/precisebank/types/genesis.go @@ -0,0 +1,70 @@ +package types + +import ( + "fmt" + + sdkmath "cosmossdk.io/math" +) + +// NewGenesisState creates a new genesis state. +func NewGenesisState( + balances FractionalBalances, + remainder sdkmath.Int, +) *GenesisState { + return &GenesisState{ + Balances: balances, + Remainder: remainder, + } +} + +// DefaultGenesisState returns a default genesis state. +func DefaultGenesisState() *GenesisState { + return NewGenesisState(FractionalBalances{}, sdkmath.ZeroInt()) +} + +// Validate performs basic validation of genesis data returning an error for +// any failed validation criteria. +func (gs *GenesisState) Validate() error { + // Validate all FractionalBalances + if err := gs.Balances.Validate(); err != nil { + return fmt.Errorf("invalid balances: %w", err) + } + + if gs.Remainder.IsNil() { + return fmt.Errorf("nil remainder amount") + } + + // Validate remainder, 0 <= remainder <= maxFractionalAmount + if gs.Remainder.IsNegative() { + return fmt.Errorf("negative remainder amount %s", gs.Remainder) + } + + if gs.Remainder.GTE(conversionFactor) { + return fmt.Errorf("remainder %v exceeds max of %v", gs.Remainder, conversionFactor.SubRaw(1)) + } + + // Determine if sum(fractionalBalances) + remainder = whole integer value + // i.e total of all fractional balances + remainder == 0 fractional digits + sum := gs.Balances.SumAmount() + sumWithRemainder := sum.Add(gs.Remainder) + + offBy := sumWithRemainder.Mod(conversionFactor) + + if !offBy.IsZero() { + return fmt.Errorf( + "sum of fractional balances %v + remainder %v is not a multiple of %v", + sum, + gs.Remainder, + conversionFactor, + ) + } + + return nil +} + +// TotalAmountWithRemainder returns the total amount of all balances in the +// genesis state, including both fractional balances and the remainder. A bit +// more verbose WithRemainder to ensure its clearly different from SumAmount(). +func (gs *GenesisState) TotalAmountWithRemainder() sdkmath.Int { + return gs.Balances.SumAmount().Add(gs.Remainder) +} diff --git a/x/precisebank/types/genesis.pb.go b/x/precisebank/types/genesis.pb.go new file mode 100644 index 00000000..b8edfa55 --- /dev/null +++ b/x/precisebank/types/genesis.pb.go @@ -0,0 +1,607 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: zgc/precisebank/v1/genesis.proto + +package types + +import ( + cosmossdk_io_math "cosmossdk.io/math" + fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// GenesisState defines the precisebank module's genesis state. +type GenesisState struct { + // balances is a list of all the balances in the precisebank module. + Balances FractionalBalances `protobuf:"bytes,1,rep,name=balances,proto3,castrepeated=FractionalBalances" json:"balances"` + // remainder is an internal value of how much extra fractional digits are + // still backed by the reserve, but not assigned to any account. + Remainder cosmossdk_io_math.Int `protobuf:"bytes,2,opt,name=remainder,proto3,customtype=cosmossdk.io/math.Int" json:"remainder"` +} + +func (m *GenesisState) Reset() { *m = GenesisState{} } +func (m *GenesisState) String() string { return proto.CompactTextString(m) } +func (*GenesisState) ProtoMessage() {} +func (*GenesisState) Descriptor() ([]byte, []int) { + return fileDescriptor_4029a0f159e1fc46, []int{0} +} +func (m *GenesisState) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenesisState.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GenesisState) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenesisState.Merge(m, src) +} +func (m *GenesisState) XXX_Size() int { + return m.Size() +} +func (m *GenesisState) XXX_DiscardUnknown() { + xxx_messageInfo_GenesisState.DiscardUnknown(m) +} + +var xxx_messageInfo_GenesisState proto.InternalMessageInfo + +func (m *GenesisState) GetBalances() FractionalBalances { + if m != nil { + return m.Balances + } + return nil +} + +// FractionalBalance defines the fractional portion of an account balance +type FractionalBalance struct { + // address is the address of the balance holder. + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + // amount indicates amount of only the fractional balance owned by the + // address. FractionalBalance currently only supports tracking 1 single asset, + // e.g. fractional balances of ukava. + Amount cosmossdk_io_math.Int `protobuf:"bytes,2,opt,name=amount,proto3,customtype=cosmossdk.io/math.Int" json:"amount"` +} + +func (m *FractionalBalance) Reset() { *m = FractionalBalance{} } +func (m *FractionalBalance) String() string { return proto.CompactTextString(m) } +func (*FractionalBalance) ProtoMessage() {} +func (*FractionalBalance) Descriptor() ([]byte, []int) { + return fileDescriptor_4029a0f159e1fc46, []int{1} +} +func (m *FractionalBalance) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *FractionalBalance) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_FractionalBalance.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *FractionalBalance) XXX_Merge(src proto.Message) { + xxx_messageInfo_FractionalBalance.Merge(m, src) +} +func (m *FractionalBalance) XXX_Size() int { + return m.Size() +} +func (m *FractionalBalance) XXX_DiscardUnknown() { + xxx_messageInfo_FractionalBalance.DiscardUnknown(m) +} + +var xxx_messageInfo_FractionalBalance proto.InternalMessageInfo + +func init() { + proto.RegisterType((*GenesisState)(nil), "zgc.precisebank.v1.GenesisState") + proto.RegisterType((*FractionalBalance)(nil), "zgc.precisebank.v1.FractionalBalance") +} + +func init() { proto.RegisterFile("zgc/precisebank/v1/genesis.proto", fileDescriptor_4029a0f159e1fc46) } + +var fileDescriptor_4029a0f159e1fc46 = []byte{ + // 357 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0xa8, 0x4a, 0x4f, 0xd6, + 0x2f, 0x28, 0x4a, 0x4d, 0xce, 0x2c, 0x4e, 0x4d, 0x4a, 0xcc, 0xcb, 0xd6, 0x2f, 0x33, 0xd4, 0x4f, + 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0xaa, 0x4a, + 0x4f, 0xd6, 0x43, 0x52, 0xa1, 0x57, 0x66, 0x28, 0x25, 0x99, 0x9c, 0x5f, 0x9c, 0x9b, 0x5f, 0x1c, + 0x0f, 0x56, 0xa1, 0x0f, 0xe1, 0x40, 0x94, 0x4b, 0x89, 0xa4, 0xe7, 0xa7, 0xe7, 0x43, 0xc4, 0x41, + 0x2c, 0x88, 0xa8, 0xd2, 0x0e, 0x46, 0x2e, 0x1e, 0x77, 0x88, 0xb1, 0xc1, 0x25, 0x89, 0x25, 0xa9, + 0x42, 0xb1, 0x5c, 0x1c, 0x49, 0x89, 0x39, 0x89, 0x79, 0xc9, 0xa9, 0xc5, 0x12, 0x8c, 0x0a, 0xcc, + 0x1a, 0xdc, 0x46, 0xaa, 0x7a, 0x98, 0x16, 0xe9, 0xb9, 0x15, 0x25, 0x26, 0x97, 0x64, 0xe6, 0xe7, + 0x25, 0xe6, 0x38, 0x41, 0x54, 0x3b, 0x49, 0x9d, 0xb8, 0x27, 0xcf, 0xb0, 0xea, 0xbe, 0xbc, 0x10, + 0x86, 0x54, 0x71, 0x10, 0xdc, 0x48, 0x21, 0x4f, 0x2e, 0xce, 0xa2, 0xd4, 0xdc, 0xc4, 0xcc, 0xbc, + 0x94, 0xd4, 0x22, 0x09, 0x26, 0x05, 0x46, 0x0d, 0x4e, 0x27, 0x6d, 0x90, 0xc6, 0x5b, 0xf7, 0xe4, + 0x45, 0x21, 0xce, 0x2d, 0x4e, 0xc9, 0xd6, 0xcb, 0xcc, 0xd7, 0xcf, 0x4d, 0x2c, 0xc9, 0xd0, 0xf3, + 0xcc, 0x2b, 0xb9, 0xb4, 0x45, 0x97, 0x0b, 0xea, 0x0f, 0xcf, 0xbc, 0x92, 0x20, 0x84, 0x6e, 0xa5, + 0x69, 0x8c, 0x5c, 0x82, 0x18, 0x76, 0x09, 0x19, 0x71, 0xb1, 0x27, 0xa6, 0xa4, 0x14, 0xa5, 0x16, + 0x83, 0x9c, 0x0f, 0x32, 0x5e, 0xe2, 0xd2, 0x16, 0x5d, 0x11, 0xa8, 0x09, 0x8e, 0x10, 0x99, 0xe0, + 0x92, 0xa2, 0xcc, 0xbc, 0xf4, 0x20, 0x98, 0x42, 0x21, 0x67, 0x2e, 0xb6, 0xc4, 0xdc, 0xfc, 0xd2, + 0xbc, 0x12, 0x72, 0x5c, 0x04, 0xd5, 0x6a, 0xc5, 0xd1, 0xb1, 0x40, 0x9e, 0xe1, 0xc5, 0x02, 0x79, + 0x06, 0x27, 0x8f, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x71, + 0xc2, 0x63, 0x39, 0x86, 0x0b, 0x8f, 0xe5, 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x88, 0xd2, 0x4b, 0xcf, + 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x37, 0x48, 0xcf, 0x49, 0x4c, 0x2a, 0xd6, + 0x37, 0x48, 0xd7, 0x4d, 0xce, 0x48, 0xcc, 0xcc, 0xd3, 0xaf, 0x40, 0x89, 0xed, 0x92, 0xca, 0x82, + 0xd4, 0xe2, 0x24, 0x36, 0x70, 0x24, 0x19, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0xc3, 0xe5, 0x62, + 0x3b, 0x0d, 0x02, 0x00, 0x00, +} + +func (m *GenesisState) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GenesisState) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size := m.Remainder.Size() + i -= size + if _, err := m.Remainder.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Balances) > 0 { + for iNdEx := len(m.Balances) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Balances[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *FractionalBalance) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *FractionalBalance) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *FractionalBalance) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size := m.Amount.Size() + i -= size + if _, err := m.Amount.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { + offset -= sovGenesis(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *GenesisState) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Balances) > 0 { + for _, e := range m.Balances { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + l = m.Remainder.Size() + n += 1 + l + sovGenesis(uint64(l)) + return n +} + +func (m *FractionalBalance) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovGenesis(uint64(l)) + } + l = m.Amount.Size() + n += 1 + l + sovGenesis(uint64(l)) + return n +} + +func sovGenesis(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGenesis(x uint64) (n int) { + return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *GenesisState) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GenesisState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Balances", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Balances = append(m.Balances, FractionalBalance{}) + if err := m.Balances[len(m.Balances)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Remainder", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Remainder.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *FractionalBalance) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: FractionalBalance: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: FractionalBalance: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenesis(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthGenesis + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupGenesis + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthGenesis + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/precisebank/types/genesis_test.go b/x/precisebank/types/genesis_test.go new file mode 100644 index 00000000..7702037d --- /dev/null +++ b/x/precisebank/types/genesis_test.go @@ -0,0 +1,295 @@ +package types_test + +import ( + "testing" + + sdkmath "cosmossdk.io/math" + "github.com/0glabs/0g-chain/chaincfg" + "github.com/0glabs/0g-chain/x/precisebank/testutil" + "github.com/0glabs/0g-chain/x/precisebank/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +func TestGenesisStateValidate_Basic(t *testing.T) { + chaincfg.SetSDKConfig() + + testCases := []struct { + name string + genesisState *types.GenesisState + wantErr string + }{ + { + "valid - default genesisState", + types.DefaultGenesisState(), + "", + }, + { + "valid - empty balances, zero remainder", + &types.GenesisState{ + Remainder: sdkmath.ZeroInt(), + }, + "", + }, + { + "valid - nil balances", + types.NewGenesisState(nil, sdkmath.ZeroInt()), + "", + }, + { + "valid - max remainder amount", + types.NewGenesisState( + types.FractionalBalances{ + types.NewFractionalBalance(sdk.AccAddress{1}.String(), sdkmath.NewInt(1)), + }, + types.ConversionFactor().SubRaw(1), + ), + "", + }, + { + "invalid - empty genesisState (nil remainder)", + &types.GenesisState{}, + "nil remainder amount", + }, + { + "valid - balances add up", + types.NewGenesisState( + types.FractionalBalances{ + types.NewFractionalBalance(sdk.AccAddress{1}.String(), sdkmath.NewInt(1)), + types.NewFractionalBalance(sdk.AccAddress{1}.String(), sdkmath.NewInt(1)), + }, + sdkmath.ZeroInt(), + ), + "invalid balances: duplicate address kava1qy0xn7za", + }, + { + "invalid - calls (single) FractionalBalance.Validate()", + types.NewGenesisState( + types.FractionalBalances{ + types.NewFractionalBalance(sdk.AccAddress{1}.String(), sdkmath.NewInt(1)), + types.NewFractionalBalance(sdk.AccAddress{2}.String(), sdkmath.NewInt(-1)), + }, + sdkmath.ZeroInt(), + ), + "invalid balances: invalid fractional balance for kava1qg7c45n6: non-positive amount -1", + }, + { + "invalid - calls (slice) FractionalBalances.Validate()", + types.NewGenesisState( + types.FractionalBalances{ + types.NewFractionalBalance(sdk.AccAddress{1}.String(), sdkmath.NewInt(1)), + types.NewFractionalBalance(sdk.AccAddress{1}.String(), sdkmath.NewInt(1)), + }, + sdkmath.ZeroInt(), + ), + "invalid balances: duplicate address kava1qy0xn7za", + }, + { + "invalid - negative remainder", + types.NewGenesisState( + types.FractionalBalances{ + types.NewFractionalBalance(sdk.AccAddress{1}.String(), sdkmath.NewInt(1)), + types.NewFractionalBalance(sdk.AccAddress{2}.String(), sdkmath.NewInt(1)), + }, + sdkmath.NewInt(-1), + ), + "negative remainder amount -1", + }, + { + "invalid - too large remainder", + types.NewGenesisState( + types.FractionalBalances{ + types.NewFractionalBalance(sdk.AccAddress{1}.String(), sdkmath.NewInt(1)), + types.NewFractionalBalance(sdk.AccAddress{2}.String(), sdkmath.NewInt(1)), + }, + types.ConversionFactor(), + ), + "remainder 1000000000000 exceeds max of 999999999999", + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(tt *testing.T) { + err := tc.genesisState.Validate() + + if tc.wantErr == "" { + require.NoError(tt, err) + } else { + require.Error(tt, err) + require.EqualError(tt, err, tc.wantErr) + } + }) + } +} + +func TestGenesisStateValidate_Total(t *testing.T) { + testCases := []struct { + name string + buildGenesisState func() *types.GenesisState + containsErr string + }{ + { + "valid - empty balances, zero remainder", + func() *types.GenesisState { + return types.NewGenesisState(nil, sdkmath.ZeroInt()) + }, + "", + }, + { + "valid - non-zero balances, zero remainder", + func() *types.GenesisState { + fbs := testutil.GenerateEqualFractionalBalances(t, 100) + require.Len(t, fbs, 100) + + return types.NewGenesisState(fbs, sdkmath.ZeroInt()) + }, + "", + }, + { + "valid - non-zero balances, non-zero remainder", + func() *types.GenesisState { + fbs, remainder := testutil.GenerateEqualFractionalBalancesWithRemainder(t, 100) + + require.Len(t, fbs, 100) + require.NotZero(t, remainder.Int64()) + + t.Log("remainder:", remainder) + + return types.NewGenesisState(fbs, remainder) + }, + "", + }, + { + "invalid - non-zero balances, invalid remainder", + func() *types.GenesisState { + fbs, remainder := testutil.GenerateEqualFractionalBalancesWithRemainder(t, 100) + + require.Len(t, fbs, 100) + require.NotZero(t, remainder.Int64()) + + // Wrong remainder - should be non-zero + return types.NewGenesisState(fbs, sdkmath.ZeroInt()) + }, + // balances are randomly generated so we can't set the exact value in the error message + // "sum of fractional balances 52885778295370 ... " + "+ remainder 0 is not a multiple of 1000000000000", + }, + { + "invalid - empty balances, non-zero remainder", + func() *types.GenesisState { + return types.NewGenesisState(types.FractionalBalances{}, sdkmath.NewInt(1)) + }, + "sum of fractional balances 0 + remainder 1 is not a multiple of 1000000000000", + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(tt *testing.T) { + err := tc.buildGenesisState().Validate() + + if tc.containsErr == "" { + require.NoError(tt, err) + } else { + require.Error(tt, err) + require.ErrorContains(tt, err, tc.containsErr) + } + }) + } +} + +func TestGenesisState_TotalAmountWithRemainder(t *testing.T) { + tests := []struct { + name string + giveBalances types.FractionalBalances + giveRemainder sdkmath.Int + wantTotalAmountWithRemainder sdkmath.Int + }{ + { + "empty balances, zero remainder", + types.FractionalBalances{}, + sdkmath.ZeroInt(), + sdkmath.ZeroInt(), + }, + { + "non-empty balances, zero remainder", + types.FractionalBalances{ + types.NewFractionalBalance(sdk.AccAddress{1}.String(), types.ConversionFactor().QuoRaw(2)), + types.NewFractionalBalance(sdk.AccAddress{2}.String(), types.ConversionFactor().QuoRaw(2)), + }, + sdkmath.ZeroInt(), + types.ConversionFactor(), + }, + { + "non-empty balances, 1 remainder", + types.FractionalBalances{ + types.NewFractionalBalance(sdk.AccAddress{1}.String(), types.ConversionFactor().QuoRaw(2)), + types.NewFractionalBalance(sdk.AccAddress{2}.String(), types.ConversionFactor().QuoRaw(2).SubRaw(1)), + }, + sdkmath.OneInt(), + types.ConversionFactor(), + }, + { + "non-empty balances, max remainder", + types.FractionalBalances{ + types.NewFractionalBalance(sdk.AccAddress{1}.String(), sdkmath.OneInt()), + }, + types.ConversionFactor().SubRaw(1), + types.ConversionFactor(), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gs := types.NewGenesisState( + tt.giveBalances, + tt.giveRemainder, + ) + + require.NoError(t, gs.Validate(), "genesis state should be valid before testing total amount") + + totalAmt := gs.TotalAmountWithRemainder() + require.Equal(t, tt.wantTotalAmountWithRemainder, totalAmt, "total amount should be balances + remainder") + }) + } +} + +func FuzzGenesisStateValidate_NonZeroRemainder(f *testing.F) { + f.Add(5) + f.Add(100) + f.Add(30) + + f.Fuzz(func(t *testing.T, count int) { + // Need at least 2 so we can generate both balances and remainder + if count < 2 { + t.Skip("count < 2") + } + + fbs, remainder := testutil.GenerateEqualFractionalBalancesWithRemainder(t, count) + + t.Logf("count: %v", count) + t.Logf("remainder: %v", remainder) + + gs := types.NewGenesisState(fbs, remainder) + require.NoError(t, gs.Validate()) + }) +} + +func FuzzGenesisStateValidate_ZeroRemainder(f *testing.F) { + f.Add(5) + f.Add(100) + f.Add(30) + + f.Fuzz(func(t *testing.T, count int) { + // Need at least 2 as 1 account with non-zero balance & no remainder is not valid + if count < 2 { + t.Skip("count < 2") + } + + fbs := testutil.GenerateEqualFractionalBalances(t, count) + + gs := types.NewGenesisState(fbs, sdkmath.ZeroInt()) + require.NoError(t, gs.Validate()) + }) +} diff --git a/x/precisebank/types/keys.go b/x/precisebank/types/keys.go new file mode 100644 index 00000000..b1b5ae1b --- /dev/null +++ b/x/precisebank/types/keys.go @@ -0,0 +1,28 @@ +package types + +import sdk "github.com/cosmos/cosmos-sdk/types" + +const ( + // ModuleName name that will be used throughout the module + ModuleName = "precisebank" + + StoreKey = ModuleName + + // RouterKey Top level router key + RouterKey = ModuleName +) + +// key prefixes for store +var ( + FractionalBalancePrefix = []byte{0x01} // address -> fractional balance +) + +// Keys for store that are not prefixed +var ( + RemainderBalanceKey = []byte{0x02} // fractional balance remainder +) + +// FractionalBalanceKey returns a key from an address +func FractionalBalanceKey(address sdk.AccAddress) []byte { + return address.Bytes() +} diff --git a/x/precisebank/types/keys_test.go b/x/precisebank/types/keys_test.go new file mode 100644 index 00000000..ca74c0d3 --- /dev/null +++ b/x/precisebank/types/keys_test.go @@ -0,0 +1,17 @@ +package types_test + +import ( + "testing" + + "github.com/0glabs/0g-chain/x/precisebank/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +func TestFractionalBalanceKey(t *testing.T) { + addr := sdk.AccAddress([]byte("test-address")) + + key := types.FractionalBalanceKey(addr) + require.Equal(t, addr.Bytes(), key) + require.Equal(t, addr, sdk.AccAddress(key), "key should be able to be converted back to address") +} diff --git a/x/precisebank/types/mocks/MockAccountKeeper.go b/x/precisebank/types/mocks/MockAccountKeeper.go new file mode 100644 index 00000000..982ba7cd --- /dev/null +++ b/x/precisebank/types/mocks/MockAccountKeeper.go @@ -0,0 +1,191 @@ +// Code generated by mockery v2.43.0. DO NOT EDIT. + +package mocks + +import ( + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + mock "github.com/stretchr/testify/mock" + + types "github.com/cosmos/cosmos-sdk/types" +) + +// MockAccountKeeper is an autogenerated mock type for the AccountKeeper type +type MockAccountKeeper struct { + mock.Mock +} + +type MockAccountKeeper_Expecter struct { + mock *mock.Mock +} + +func (_m *MockAccountKeeper) EXPECT() *MockAccountKeeper_Expecter { + return &MockAccountKeeper_Expecter{mock: &_m.Mock} +} + +// GetModuleAccount provides a mock function with given fields: ctx, moduleName +func (_m *MockAccountKeeper) GetModuleAccount(ctx types.Context, moduleName string) authtypes.ModuleAccountI { + ret := _m.Called(ctx, moduleName) + + if len(ret) == 0 { + panic("no return value specified for GetModuleAccount") + } + + var r0 authtypes.ModuleAccountI + if rf, ok := ret.Get(0).(func(types.Context, string) authtypes.ModuleAccountI); ok { + r0 = rf(ctx, moduleName) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(authtypes.ModuleAccountI) + } + } + + return r0 +} + +// MockAccountKeeper_GetModuleAccount_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetModuleAccount' +type MockAccountKeeper_GetModuleAccount_Call struct { + *mock.Call +} + +// GetModuleAccount is a helper method to define mock.On call +// - ctx types.Context +// - moduleName string +func (_e *MockAccountKeeper_Expecter) GetModuleAccount(ctx interface{}, moduleName interface{}) *MockAccountKeeper_GetModuleAccount_Call { + return &MockAccountKeeper_GetModuleAccount_Call{Call: _e.mock.On("GetModuleAccount", ctx, moduleName)} +} + +func (_c *MockAccountKeeper_GetModuleAccount_Call) Run(run func(ctx types.Context, moduleName string)) *MockAccountKeeper_GetModuleAccount_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Context), args[1].(string)) + }) + return _c +} + +func (_c *MockAccountKeeper_GetModuleAccount_Call) Return(_a0 authtypes.ModuleAccountI) *MockAccountKeeper_GetModuleAccount_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockAccountKeeper_GetModuleAccount_Call) RunAndReturn(run func(types.Context, string) authtypes.ModuleAccountI) *MockAccountKeeper_GetModuleAccount_Call { + _c.Call.Return(run) + return _c +} + +// GetModuleAddress provides a mock function with given fields: moduleName +func (_m *MockAccountKeeper) GetModuleAddress(moduleName string) types.AccAddress { + ret := _m.Called(moduleName) + + if len(ret) == 0 { + panic("no return value specified for GetModuleAddress") + } + + var r0 types.AccAddress + if rf, ok := ret.Get(0).(func(string) types.AccAddress); ok { + r0 = rf(moduleName) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(types.AccAddress) + } + } + + return r0 +} + +// MockAccountKeeper_GetModuleAddress_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetModuleAddress' +type MockAccountKeeper_GetModuleAddress_Call struct { + *mock.Call +} + +// GetModuleAddress is a helper method to define mock.On call +// - moduleName string +func (_e *MockAccountKeeper_Expecter) GetModuleAddress(moduleName interface{}) *MockAccountKeeper_GetModuleAddress_Call { + return &MockAccountKeeper_GetModuleAddress_Call{Call: _e.mock.On("GetModuleAddress", moduleName)} +} + +func (_c *MockAccountKeeper_GetModuleAddress_Call) Run(run func(moduleName string)) *MockAccountKeeper_GetModuleAddress_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *MockAccountKeeper_GetModuleAddress_Call) Return(_a0 types.AccAddress) *MockAccountKeeper_GetModuleAddress_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockAccountKeeper_GetModuleAddress_Call) RunAndReturn(run func(string) types.AccAddress) *MockAccountKeeper_GetModuleAddress_Call { + _c.Call.Return(run) + return _c +} + +// GetSequence provides a mock function with given fields: _a0, _a1 +func (_m *MockAccountKeeper) GetSequence(_a0 types.Context, _a1 types.AccAddress) (uint64, error) { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for GetSequence") + } + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(types.Context, types.AccAddress) (uint64, error)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(types.Context, types.AccAddress) uint64); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(types.Context, types.AccAddress) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockAccountKeeper_GetSequence_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetSequence' +type MockAccountKeeper_GetSequence_Call struct { + *mock.Call +} + +// GetSequence is a helper method to define mock.On call +// - _a0 types.Context +// - _a1 types.AccAddress +func (_e *MockAccountKeeper_Expecter) GetSequence(_a0 interface{}, _a1 interface{}) *MockAccountKeeper_GetSequence_Call { + return &MockAccountKeeper_GetSequence_Call{Call: _e.mock.On("GetSequence", _a0, _a1)} +} + +func (_c *MockAccountKeeper_GetSequence_Call) Run(run func(_a0 types.Context, _a1 types.AccAddress)) *MockAccountKeeper_GetSequence_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Context), args[1].(types.AccAddress)) + }) + return _c +} + +func (_c *MockAccountKeeper_GetSequence_Call) Return(_a0 uint64, _a1 error) *MockAccountKeeper_GetSequence_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockAccountKeeper_GetSequence_Call) RunAndReturn(run func(types.Context, types.AccAddress) (uint64, error)) *MockAccountKeeper_GetSequence_Call { + _c.Call.Return(run) + return _c +} + +// NewMockAccountKeeper creates a new instance of MockAccountKeeper. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewMockAccountKeeper(t interface { + mock.TestingT + Cleanup(func()) +}) *MockAccountKeeper { + mock := &MockAccountKeeper{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/x/precisebank/types/mocks/MockBankKeeper.go b/x/precisebank/types/mocks/MockBankKeeper.go new file mode 100644 index 00000000..cb823410 --- /dev/null +++ b/x/precisebank/types/mocks/MockBankKeeper.go @@ -0,0 +1,578 @@ +// Code generated by mockery v2.43.0. DO NOT EDIT. + +package mocks + +import ( + mock "github.com/stretchr/testify/mock" + + types "github.com/cosmos/cosmos-sdk/types" +) + +// MockBankKeeper is an autogenerated mock type for the BankKeeper type +type MockBankKeeper struct { + mock.Mock +} + +type MockBankKeeper_Expecter struct { + mock *mock.Mock +} + +func (_m *MockBankKeeper) EXPECT() *MockBankKeeper_Expecter { + return &MockBankKeeper_Expecter{mock: &_m.Mock} +} + +// BlockedAddr provides a mock function with given fields: addr +func (_m *MockBankKeeper) BlockedAddr(addr types.AccAddress) bool { + ret := _m.Called(addr) + + if len(ret) == 0 { + panic("no return value specified for BlockedAddr") + } + + var r0 bool + if rf, ok := ret.Get(0).(func(types.AccAddress) bool); ok { + r0 = rf(addr) + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + +// MockBankKeeper_BlockedAddr_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BlockedAddr' +type MockBankKeeper_BlockedAddr_Call struct { + *mock.Call +} + +// BlockedAddr is a helper method to define mock.On call +// - addr types.AccAddress +func (_e *MockBankKeeper_Expecter) BlockedAddr(addr interface{}) *MockBankKeeper_BlockedAddr_Call { + return &MockBankKeeper_BlockedAddr_Call{Call: _e.mock.On("BlockedAddr", addr)} +} + +func (_c *MockBankKeeper_BlockedAddr_Call) Run(run func(addr types.AccAddress)) *MockBankKeeper_BlockedAddr_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.AccAddress)) + }) + return _c +} + +func (_c *MockBankKeeper_BlockedAddr_Call) Return(_a0 bool) *MockBankKeeper_BlockedAddr_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockBankKeeper_BlockedAddr_Call) RunAndReturn(run func(types.AccAddress) bool) *MockBankKeeper_BlockedAddr_Call { + _c.Call.Return(run) + return _c +} + +// BurnCoins provides a mock function with given fields: ctx, moduleName, amt +func (_m *MockBankKeeper) BurnCoins(ctx types.Context, moduleName string, amt types.Coins) error { + ret := _m.Called(ctx, moduleName, amt) + + if len(ret) == 0 { + panic("no return value specified for BurnCoins") + } + + var r0 error + if rf, ok := ret.Get(0).(func(types.Context, string, types.Coins) error); ok { + r0 = rf(ctx, moduleName, amt) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// MockBankKeeper_BurnCoins_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BurnCoins' +type MockBankKeeper_BurnCoins_Call struct { + *mock.Call +} + +// BurnCoins is a helper method to define mock.On call +// - ctx types.Context +// - moduleName string +// - amt types.Coins +func (_e *MockBankKeeper_Expecter) BurnCoins(ctx interface{}, moduleName interface{}, amt interface{}) *MockBankKeeper_BurnCoins_Call { + return &MockBankKeeper_BurnCoins_Call{Call: _e.mock.On("BurnCoins", ctx, moduleName, amt)} +} + +func (_c *MockBankKeeper_BurnCoins_Call) Run(run func(ctx types.Context, moduleName string, amt types.Coins)) *MockBankKeeper_BurnCoins_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Context), args[1].(string), args[2].(types.Coins)) + }) + return _c +} + +func (_c *MockBankKeeper_BurnCoins_Call) Return(_a0 error) *MockBankKeeper_BurnCoins_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockBankKeeper_BurnCoins_Call) RunAndReturn(run func(types.Context, string, types.Coins) error) *MockBankKeeper_BurnCoins_Call { + _c.Call.Return(run) + return _c +} + +// GetBalance provides a mock function with given fields: ctx, addr, denom +func (_m *MockBankKeeper) GetBalance(ctx types.Context, addr types.AccAddress, denom string) types.Coin { + ret := _m.Called(ctx, addr, denom) + + if len(ret) == 0 { + panic("no return value specified for GetBalance") + } + + var r0 types.Coin + if rf, ok := ret.Get(0).(func(types.Context, types.AccAddress, string) types.Coin); ok { + r0 = rf(ctx, addr, denom) + } else { + r0 = ret.Get(0).(types.Coin) + } + + return r0 +} + +// MockBankKeeper_GetBalance_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetBalance' +type MockBankKeeper_GetBalance_Call struct { + *mock.Call +} + +// GetBalance is a helper method to define mock.On call +// - ctx types.Context +// - addr types.AccAddress +// - denom string +func (_e *MockBankKeeper_Expecter) GetBalance(ctx interface{}, addr interface{}, denom interface{}) *MockBankKeeper_GetBalance_Call { + return &MockBankKeeper_GetBalance_Call{Call: _e.mock.On("GetBalance", ctx, addr, denom)} +} + +func (_c *MockBankKeeper_GetBalance_Call) Run(run func(ctx types.Context, addr types.AccAddress, denom string)) *MockBankKeeper_GetBalance_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Context), args[1].(types.AccAddress), args[2].(string)) + }) + return _c +} + +func (_c *MockBankKeeper_GetBalance_Call) Return(_a0 types.Coin) *MockBankKeeper_GetBalance_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockBankKeeper_GetBalance_Call) RunAndReturn(run func(types.Context, types.AccAddress, string) types.Coin) *MockBankKeeper_GetBalance_Call { + _c.Call.Return(run) + return _c +} + +// GetSupply provides a mock function with given fields: ctx, denom +func (_m *MockBankKeeper) GetSupply(ctx types.Context, denom string) types.Coin { + ret := _m.Called(ctx, denom) + + if len(ret) == 0 { + panic("no return value specified for GetSupply") + } + + var r0 types.Coin + if rf, ok := ret.Get(0).(func(types.Context, string) types.Coin); ok { + r0 = rf(ctx, denom) + } else { + r0 = ret.Get(0).(types.Coin) + } + + return r0 +} + +// MockBankKeeper_GetSupply_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetSupply' +type MockBankKeeper_GetSupply_Call struct { + *mock.Call +} + +// GetSupply is a helper method to define mock.On call +// - ctx types.Context +// - denom string +func (_e *MockBankKeeper_Expecter) GetSupply(ctx interface{}, denom interface{}) *MockBankKeeper_GetSupply_Call { + return &MockBankKeeper_GetSupply_Call{Call: _e.mock.On("GetSupply", ctx, denom)} +} + +func (_c *MockBankKeeper_GetSupply_Call) Run(run func(ctx types.Context, denom string)) *MockBankKeeper_GetSupply_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Context), args[1].(string)) + }) + return _c +} + +func (_c *MockBankKeeper_GetSupply_Call) Return(_a0 types.Coin) *MockBankKeeper_GetSupply_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockBankKeeper_GetSupply_Call) RunAndReturn(run func(types.Context, string) types.Coin) *MockBankKeeper_GetSupply_Call { + _c.Call.Return(run) + return _c +} + +// IsSendEnabledCoins provides a mock function with given fields: ctx, coins +func (_m *MockBankKeeper) IsSendEnabledCoins(ctx types.Context, coins ...types.Coin) error { + _va := make([]interface{}, len(coins)) + for _i := range coins { + _va[_i] = coins[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for IsSendEnabledCoins") + } + + var r0 error + if rf, ok := ret.Get(0).(func(types.Context, ...types.Coin) error); ok { + r0 = rf(ctx, coins...) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// MockBankKeeper_IsSendEnabledCoins_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'IsSendEnabledCoins' +type MockBankKeeper_IsSendEnabledCoins_Call struct { + *mock.Call +} + +// IsSendEnabledCoins is a helper method to define mock.On call +// - ctx types.Context +// - coins ...types.Coin +func (_e *MockBankKeeper_Expecter) IsSendEnabledCoins(ctx interface{}, coins ...interface{}) *MockBankKeeper_IsSendEnabledCoins_Call { + return &MockBankKeeper_IsSendEnabledCoins_Call{Call: _e.mock.On("IsSendEnabledCoins", + append([]interface{}{ctx}, coins...)...)} +} + +func (_c *MockBankKeeper_IsSendEnabledCoins_Call) Run(run func(ctx types.Context, coins ...types.Coin)) *MockBankKeeper_IsSendEnabledCoins_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]types.Coin, len(args)-1) + for i, a := range args[1:] { + if a != nil { + variadicArgs[i] = a.(types.Coin) + } + } + run(args[0].(types.Context), variadicArgs...) + }) + return _c +} + +func (_c *MockBankKeeper_IsSendEnabledCoins_Call) Return(_a0 error) *MockBankKeeper_IsSendEnabledCoins_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockBankKeeper_IsSendEnabledCoins_Call) RunAndReturn(run func(types.Context, ...types.Coin) error) *MockBankKeeper_IsSendEnabledCoins_Call { + _c.Call.Return(run) + return _c +} + +// MintCoins provides a mock function with given fields: ctx, moduleName, amt +func (_m *MockBankKeeper) MintCoins(ctx types.Context, moduleName string, amt types.Coins) error { + ret := _m.Called(ctx, moduleName, amt) + + if len(ret) == 0 { + panic("no return value specified for MintCoins") + } + + var r0 error + if rf, ok := ret.Get(0).(func(types.Context, string, types.Coins) error); ok { + r0 = rf(ctx, moduleName, amt) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// MockBankKeeper_MintCoins_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'MintCoins' +type MockBankKeeper_MintCoins_Call struct { + *mock.Call +} + +// MintCoins is a helper method to define mock.On call +// - ctx types.Context +// - moduleName string +// - amt types.Coins +func (_e *MockBankKeeper_Expecter) MintCoins(ctx interface{}, moduleName interface{}, amt interface{}) *MockBankKeeper_MintCoins_Call { + return &MockBankKeeper_MintCoins_Call{Call: _e.mock.On("MintCoins", ctx, moduleName, amt)} +} + +func (_c *MockBankKeeper_MintCoins_Call) Run(run func(ctx types.Context, moduleName string, amt types.Coins)) *MockBankKeeper_MintCoins_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Context), args[1].(string), args[2].(types.Coins)) + }) + return _c +} + +func (_c *MockBankKeeper_MintCoins_Call) Return(_a0 error) *MockBankKeeper_MintCoins_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockBankKeeper_MintCoins_Call) RunAndReturn(run func(types.Context, string, types.Coins) error) *MockBankKeeper_MintCoins_Call { + _c.Call.Return(run) + return _c +} + +// SendCoins provides a mock function with given fields: ctx, fromAddr, toAddr, amt +func (_m *MockBankKeeper) SendCoins(ctx types.Context, fromAddr types.AccAddress, toAddr types.AccAddress, amt types.Coins) error { + ret := _m.Called(ctx, fromAddr, toAddr, amt) + + if len(ret) == 0 { + panic("no return value specified for SendCoins") + } + + var r0 error + if rf, ok := ret.Get(0).(func(types.Context, types.AccAddress, types.AccAddress, types.Coins) error); ok { + r0 = rf(ctx, fromAddr, toAddr, amt) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// MockBankKeeper_SendCoins_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendCoins' +type MockBankKeeper_SendCoins_Call struct { + *mock.Call +} + +// SendCoins is a helper method to define mock.On call +// - ctx types.Context +// - fromAddr types.AccAddress +// - toAddr types.AccAddress +// - amt types.Coins +func (_e *MockBankKeeper_Expecter) SendCoins(ctx interface{}, fromAddr interface{}, toAddr interface{}, amt interface{}) *MockBankKeeper_SendCoins_Call { + return &MockBankKeeper_SendCoins_Call{Call: _e.mock.On("SendCoins", ctx, fromAddr, toAddr, amt)} +} + +func (_c *MockBankKeeper_SendCoins_Call) Run(run func(ctx types.Context, fromAddr types.AccAddress, toAddr types.AccAddress, amt types.Coins)) *MockBankKeeper_SendCoins_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Context), args[1].(types.AccAddress), args[2].(types.AccAddress), args[3].(types.Coins)) + }) + return _c +} + +func (_c *MockBankKeeper_SendCoins_Call) Return(_a0 error) *MockBankKeeper_SendCoins_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockBankKeeper_SendCoins_Call) RunAndReturn(run func(types.Context, types.AccAddress, types.AccAddress, types.Coins) error) *MockBankKeeper_SendCoins_Call { + _c.Call.Return(run) + return _c +} + +// SendCoinsFromAccountToModule provides a mock function with given fields: ctx, senderAddr, recipientModule, amt +func (_m *MockBankKeeper) SendCoinsFromAccountToModule(ctx types.Context, senderAddr types.AccAddress, recipientModule string, amt types.Coins) error { + ret := _m.Called(ctx, senderAddr, recipientModule, amt) + + if len(ret) == 0 { + panic("no return value specified for SendCoinsFromAccountToModule") + } + + var r0 error + if rf, ok := ret.Get(0).(func(types.Context, types.AccAddress, string, types.Coins) error); ok { + r0 = rf(ctx, senderAddr, recipientModule, amt) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// MockBankKeeper_SendCoinsFromAccountToModule_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendCoinsFromAccountToModule' +type MockBankKeeper_SendCoinsFromAccountToModule_Call struct { + *mock.Call +} + +// SendCoinsFromAccountToModule is a helper method to define mock.On call +// - ctx types.Context +// - senderAddr types.AccAddress +// - recipientModule string +// - amt types.Coins +func (_e *MockBankKeeper_Expecter) SendCoinsFromAccountToModule(ctx interface{}, senderAddr interface{}, recipientModule interface{}, amt interface{}) *MockBankKeeper_SendCoinsFromAccountToModule_Call { + return &MockBankKeeper_SendCoinsFromAccountToModule_Call{Call: _e.mock.On("SendCoinsFromAccountToModule", ctx, senderAddr, recipientModule, amt)} +} + +func (_c *MockBankKeeper_SendCoinsFromAccountToModule_Call) Run(run func(ctx types.Context, senderAddr types.AccAddress, recipientModule string, amt types.Coins)) *MockBankKeeper_SendCoinsFromAccountToModule_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Context), args[1].(types.AccAddress), args[2].(string), args[3].(types.Coins)) + }) + return _c +} + +func (_c *MockBankKeeper_SendCoinsFromAccountToModule_Call) Return(_a0 error) *MockBankKeeper_SendCoinsFromAccountToModule_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockBankKeeper_SendCoinsFromAccountToModule_Call) RunAndReturn(run func(types.Context, types.AccAddress, string, types.Coins) error) *MockBankKeeper_SendCoinsFromAccountToModule_Call { + _c.Call.Return(run) + return _c +} + +// SendCoinsFromModuleToAccount provides a mock function with given fields: ctx, senderModule, recipientAddr, amt +func (_m *MockBankKeeper) SendCoinsFromModuleToAccount(ctx types.Context, senderModule string, recipientAddr types.AccAddress, amt types.Coins) error { + ret := _m.Called(ctx, senderModule, recipientAddr, amt) + + if len(ret) == 0 { + panic("no return value specified for SendCoinsFromModuleToAccount") + } + + var r0 error + if rf, ok := ret.Get(0).(func(types.Context, string, types.AccAddress, types.Coins) error); ok { + r0 = rf(ctx, senderModule, recipientAddr, amt) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// MockBankKeeper_SendCoinsFromModuleToAccount_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendCoinsFromModuleToAccount' +type MockBankKeeper_SendCoinsFromModuleToAccount_Call struct { + *mock.Call +} + +// SendCoinsFromModuleToAccount is a helper method to define mock.On call +// - ctx types.Context +// - senderModule string +// - recipientAddr types.AccAddress +// - amt types.Coins +func (_e *MockBankKeeper_Expecter) SendCoinsFromModuleToAccount(ctx interface{}, senderModule interface{}, recipientAddr interface{}, amt interface{}) *MockBankKeeper_SendCoinsFromModuleToAccount_Call { + return &MockBankKeeper_SendCoinsFromModuleToAccount_Call{Call: _e.mock.On("SendCoinsFromModuleToAccount", ctx, senderModule, recipientAddr, amt)} +} + +func (_c *MockBankKeeper_SendCoinsFromModuleToAccount_Call) Run(run func(ctx types.Context, senderModule string, recipientAddr types.AccAddress, amt types.Coins)) *MockBankKeeper_SendCoinsFromModuleToAccount_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Context), args[1].(string), args[2].(types.AccAddress), args[3].(types.Coins)) + }) + return _c +} + +func (_c *MockBankKeeper_SendCoinsFromModuleToAccount_Call) Return(_a0 error) *MockBankKeeper_SendCoinsFromModuleToAccount_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockBankKeeper_SendCoinsFromModuleToAccount_Call) RunAndReturn(run func(types.Context, string, types.AccAddress, types.Coins) error) *MockBankKeeper_SendCoinsFromModuleToAccount_Call { + _c.Call.Return(run) + return _c +} + +// SendCoinsFromModuleToModule provides a mock function with given fields: ctx, senderModule, recipientModule, amt +func (_m *MockBankKeeper) SendCoinsFromModuleToModule(ctx types.Context, senderModule string, recipientModule string, amt types.Coins) error { + ret := _m.Called(ctx, senderModule, recipientModule, amt) + + if len(ret) == 0 { + panic("no return value specified for SendCoinsFromModuleToModule") + } + + var r0 error + if rf, ok := ret.Get(0).(func(types.Context, string, string, types.Coins) error); ok { + r0 = rf(ctx, senderModule, recipientModule, amt) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// MockBankKeeper_SendCoinsFromModuleToModule_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendCoinsFromModuleToModule' +type MockBankKeeper_SendCoinsFromModuleToModule_Call struct { + *mock.Call +} + +// SendCoinsFromModuleToModule is a helper method to define mock.On call +// - ctx types.Context +// - senderModule string +// - recipientModule string +// - amt types.Coins +func (_e *MockBankKeeper_Expecter) SendCoinsFromModuleToModule(ctx interface{}, senderModule interface{}, recipientModule interface{}, amt interface{}) *MockBankKeeper_SendCoinsFromModuleToModule_Call { + return &MockBankKeeper_SendCoinsFromModuleToModule_Call{Call: _e.mock.On("SendCoinsFromModuleToModule", ctx, senderModule, recipientModule, amt)} +} + +func (_c *MockBankKeeper_SendCoinsFromModuleToModule_Call) Run(run func(ctx types.Context, senderModule string, recipientModule string, amt types.Coins)) *MockBankKeeper_SendCoinsFromModuleToModule_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Context), args[1].(string), args[2].(string), args[3].(types.Coins)) + }) + return _c +} + +func (_c *MockBankKeeper_SendCoinsFromModuleToModule_Call) Return(_a0 error) *MockBankKeeper_SendCoinsFromModuleToModule_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockBankKeeper_SendCoinsFromModuleToModule_Call) RunAndReturn(run func(types.Context, string, string, types.Coins) error) *MockBankKeeper_SendCoinsFromModuleToModule_Call { + _c.Call.Return(run) + return _c +} + +// SpendableCoin provides a mock function with given fields: ctx, addr, denom +func (_m *MockBankKeeper) SpendableCoin(ctx types.Context, addr types.AccAddress, denom string) types.Coin { + ret := _m.Called(ctx, addr, denom) + + if len(ret) == 0 { + panic("no return value specified for SpendableCoin") + } + + var r0 types.Coin + if rf, ok := ret.Get(0).(func(types.Context, types.AccAddress, string) types.Coin); ok { + r0 = rf(ctx, addr, denom) + } else { + r0 = ret.Get(0).(types.Coin) + } + + return r0 +} + +// MockBankKeeper_SpendableCoin_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SpendableCoin' +type MockBankKeeper_SpendableCoin_Call struct { + *mock.Call +} + +// SpendableCoin is a helper method to define mock.On call +// - ctx types.Context +// - addr types.AccAddress +// - denom string +func (_e *MockBankKeeper_Expecter) SpendableCoin(ctx interface{}, addr interface{}, denom interface{}) *MockBankKeeper_SpendableCoin_Call { + return &MockBankKeeper_SpendableCoin_Call{Call: _e.mock.On("SpendableCoin", ctx, addr, denom)} +} + +func (_c *MockBankKeeper_SpendableCoin_Call) Run(run func(ctx types.Context, addr types.AccAddress, denom string)) *MockBankKeeper_SpendableCoin_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Context), args[1].(types.AccAddress), args[2].(string)) + }) + return _c +} + +func (_c *MockBankKeeper_SpendableCoin_Call) Return(_a0 types.Coin) *MockBankKeeper_SpendableCoin_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockBankKeeper_SpendableCoin_Call) RunAndReturn(run func(types.Context, types.AccAddress, string) types.Coin) *MockBankKeeper_SpendableCoin_Call { + _c.Call.Return(run) + return _c +} + +// NewMockBankKeeper creates a new instance of MockBankKeeper. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewMockBankKeeper(t interface { + mock.TestingT + Cleanup(func()) +}) *MockBankKeeper { + mock := &MockBankKeeper{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/x/precisebank/types/query.pb.go b/x/precisebank/types/query.pb.go new file mode 100644 index 00000000..33bfdaf0 --- /dev/null +++ b/x/precisebank/types/query.pb.go @@ -0,0 +1,1245 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: zgc/precisebank/v1/query.proto + +package types + +import ( + context "context" + fmt "fmt" + types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/cosmos/gogoproto/gogoproto" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + _ "google.golang.org/genproto/googleapis/api/annotations" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// QueryTotalFractionalBalancesRequest defines the request type for Query/TotalFractionalBalances method. +type QueryTotalFractionalBalancesRequest struct { +} + +func (m *QueryTotalFractionalBalancesRequest) Reset() { *m = QueryTotalFractionalBalancesRequest{} } +func (m *QueryTotalFractionalBalancesRequest) String() string { return proto.CompactTextString(m) } +func (*QueryTotalFractionalBalancesRequest) ProtoMessage() {} +func (*QueryTotalFractionalBalancesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_c77e9b73389f3988, []int{0} +} +func (m *QueryTotalFractionalBalancesRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryTotalFractionalBalancesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryTotalFractionalBalancesRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryTotalFractionalBalancesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryTotalFractionalBalancesRequest.Merge(m, src) +} +func (m *QueryTotalFractionalBalancesRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryTotalFractionalBalancesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryTotalFractionalBalancesRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryTotalFractionalBalancesRequest proto.InternalMessageInfo + +// QueryTotalFractionalBalancesResponse defines the response type for Query/TotalFractionalBalances method. +type QueryTotalFractionalBalancesResponse struct { + // total is the total sum of all fractional balances managed by the precisebank + // module. + Total types.Coin `protobuf:"bytes,1,opt,name=total,proto3" json:"total"` +} + +func (m *QueryTotalFractionalBalancesResponse) Reset() { *m = QueryTotalFractionalBalancesResponse{} } +func (m *QueryTotalFractionalBalancesResponse) String() string { return proto.CompactTextString(m) } +func (*QueryTotalFractionalBalancesResponse) ProtoMessage() {} +func (*QueryTotalFractionalBalancesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_c77e9b73389f3988, []int{1} +} +func (m *QueryTotalFractionalBalancesResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryTotalFractionalBalancesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryTotalFractionalBalancesResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryTotalFractionalBalancesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryTotalFractionalBalancesResponse.Merge(m, src) +} +func (m *QueryTotalFractionalBalancesResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryTotalFractionalBalancesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryTotalFractionalBalancesResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryTotalFractionalBalancesResponse proto.InternalMessageInfo + +// QueryRemainderRequest defines the request type for Query/Remainder method. +type QueryRemainderRequest struct { +} + +func (m *QueryRemainderRequest) Reset() { *m = QueryRemainderRequest{} } +func (m *QueryRemainderRequest) String() string { return proto.CompactTextString(m) } +func (*QueryRemainderRequest) ProtoMessage() {} +func (*QueryRemainderRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_c77e9b73389f3988, []int{2} +} +func (m *QueryRemainderRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryRemainderRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryRemainderRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryRemainderRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryRemainderRequest.Merge(m, src) +} +func (m *QueryRemainderRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryRemainderRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryRemainderRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryRemainderRequest proto.InternalMessageInfo + +// QueryRemainderResponse defines the response type for Query/Remainder method. +type QueryRemainderResponse struct { + // remainder is the amount backed by the reserve, but not yet owned by any + // account, i.e. not in circulation. + Remainder types.Coin `protobuf:"bytes,1,opt,name=remainder,proto3" json:"remainder"` +} + +func (m *QueryRemainderResponse) Reset() { *m = QueryRemainderResponse{} } +func (m *QueryRemainderResponse) String() string { return proto.CompactTextString(m) } +func (*QueryRemainderResponse) ProtoMessage() {} +func (*QueryRemainderResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_c77e9b73389f3988, []int{3} +} +func (m *QueryRemainderResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryRemainderResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryRemainderResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryRemainderResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryRemainderResponse.Merge(m, src) +} +func (m *QueryRemainderResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryRemainderResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryRemainderResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryRemainderResponse proto.InternalMessageInfo + +// QueryFractionalBalanceRequest defines the request type for Query/FractionalBalance method. +type QueryFractionalBalanceRequest struct { + // address is the account address to query fractional balance for. + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` +} + +func (m *QueryFractionalBalanceRequest) Reset() { *m = QueryFractionalBalanceRequest{} } +func (m *QueryFractionalBalanceRequest) String() string { return proto.CompactTextString(m) } +func (*QueryFractionalBalanceRequest) ProtoMessage() {} +func (*QueryFractionalBalanceRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_c77e9b73389f3988, []int{4} +} +func (m *QueryFractionalBalanceRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryFractionalBalanceRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryFractionalBalanceRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryFractionalBalanceRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryFractionalBalanceRequest.Merge(m, src) +} +func (m *QueryFractionalBalanceRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryFractionalBalanceRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryFractionalBalanceRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryFractionalBalanceRequest proto.InternalMessageInfo + +// QueryFractionalBalanceResponse defines the response type for Query/FractionalBalance method. +type QueryFractionalBalanceResponse struct { + // fractional_balance is the fractional balance of the address. + FractionalBalance types.Coin `protobuf:"bytes,1,opt,name=fractional_balance,json=fractionalBalance,proto3" json:"fractional_balance"` +} + +func (m *QueryFractionalBalanceResponse) Reset() { *m = QueryFractionalBalanceResponse{} } +func (m *QueryFractionalBalanceResponse) String() string { return proto.CompactTextString(m) } +func (*QueryFractionalBalanceResponse) ProtoMessage() {} +func (*QueryFractionalBalanceResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_c77e9b73389f3988, []int{5} +} +func (m *QueryFractionalBalanceResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryFractionalBalanceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryFractionalBalanceResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryFractionalBalanceResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryFractionalBalanceResponse.Merge(m, src) +} +func (m *QueryFractionalBalanceResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryFractionalBalanceResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryFractionalBalanceResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryFractionalBalanceResponse proto.InternalMessageInfo + +func init() { + proto.RegisterType((*QueryTotalFractionalBalancesRequest)(nil), "zgc.precisebank.v1.QueryTotalFractionalBalancesRequest") + proto.RegisterType((*QueryTotalFractionalBalancesResponse)(nil), "zgc.precisebank.v1.QueryTotalFractionalBalancesResponse") + proto.RegisterType((*QueryRemainderRequest)(nil), "zgc.precisebank.v1.QueryRemainderRequest") + proto.RegisterType((*QueryRemainderResponse)(nil), "zgc.precisebank.v1.QueryRemainderResponse") + proto.RegisterType((*QueryFractionalBalanceRequest)(nil), "zgc.precisebank.v1.QueryFractionalBalanceRequest") + proto.RegisterType((*QueryFractionalBalanceResponse)(nil), "zgc.precisebank.v1.QueryFractionalBalanceResponse") +} + +func init() { proto.RegisterFile("zgc/precisebank/v1/query.proto", fileDescriptor_c77e9b73389f3988) } + +var fileDescriptor_c77e9b73389f3988 = []byte{ + // 491 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x94, 0x4f, 0x6b, 0x14, 0x31, + 0x18, 0xc6, 0x67, 0xa4, 0x55, 0x36, 0x9e, 0x1a, 0xd4, 0xd6, 0xa1, 0x46, 0x19, 0x2b, 0xa8, 0x68, + 0xb2, 0xb3, 0x2a, 0xd5, 0x83, 0x97, 0x15, 0x3c, 0x89, 0xe0, 0x22, 0x08, 0x82, 0x94, 0x4c, 0x36, + 0x4d, 0x07, 0x67, 0x93, 0xe9, 0x24, 0xbb, 0xd8, 0x8a, 0x17, 0x4f, 0x5e, 0x04, 0xc1, 0x8f, 0xe2, + 0x37, 0xf0, 0xb4, 0xc7, 0x82, 0x17, 0x4f, 0xa2, 0xbb, 0x7e, 0x10, 0x99, 0x4c, 0x76, 0xd5, 0x9d, + 0x4e, 0x99, 0xbd, 0x65, 0xf2, 0xfe, 0x79, 0x7e, 0x6f, 0xde, 0x87, 0x01, 0xe8, 0x50, 0x30, 0x92, + 0xe5, 0x9c, 0x25, 0x9a, 0xc7, 0x54, 0xbe, 0x26, 0xa3, 0x88, 0xec, 0x0f, 0x79, 0x7e, 0x80, 0xb3, + 0x5c, 0x19, 0x05, 0xe1, 0xa1, 0x60, 0xf8, 0x9f, 0x38, 0x1e, 0x45, 0x01, 0x62, 0x4a, 0x0f, 0x94, + 0x26, 0x31, 0xd5, 0x9c, 0x8c, 0xa2, 0x98, 0x1b, 0x1a, 0x11, 0xa6, 0x12, 0x59, 0xd6, 0x04, 0xe7, + 0x84, 0x12, 0xca, 0x1e, 0x49, 0x71, 0x72, 0xb7, 0x9b, 0x42, 0x29, 0x91, 0x72, 0x42, 0xb3, 0x84, + 0x50, 0x29, 0x95, 0xa1, 0x26, 0x51, 0x52, 0x97, 0xd1, 0xf0, 0x1a, 0xb8, 0xfa, 0xac, 0x90, 0x7d, + 0xae, 0x0c, 0x4d, 0x1f, 0xe7, 0x94, 0x15, 0x41, 0x9a, 0x76, 0x69, 0x4a, 0x25, 0xe3, 0xba, 0xc7, + 0xf7, 0x87, 0x5c, 0x9b, 0xf0, 0x15, 0xd8, 0x3a, 0x39, 0x4d, 0x67, 0x4a, 0x6a, 0x0e, 0xef, 0x81, + 0x55, 0x53, 0xa4, 0x6c, 0xf8, 0x57, 0xfc, 0xeb, 0x67, 0x3b, 0x17, 0x71, 0x89, 0x8c, 0x0b, 0x64, + 0xec, 0x90, 0xf1, 0x23, 0x95, 0xc8, 0xee, 0xca, 0xf8, 0xc7, 0x65, 0xaf, 0x57, 0x66, 0x87, 0xeb, + 0xe0, 0xbc, 0x6d, 0xdf, 0xe3, 0x03, 0x9a, 0xc8, 0x3e, 0xcf, 0x67, 0xba, 0x2f, 0xc0, 0x85, 0xc5, + 0x80, 0x53, 0x7a, 0x08, 0x5a, 0xf9, 0xec, 0xb2, 0xa9, 0xda, 0xdf, 0x8a, 0xf0, 0x01, 0xb8, 0x64, + 0x1b, 0x57, 0x66, 0x71, 0xca, 0x70, 0x03, 0x9c, 0xa1, 0xfd, 0x7e, 0xce, 0xb5, 0xb6, 0xdd, 0x5b, + 0xbd, 0xd9, 0x67, 0x98, 0x01, 0x54, 0x57, 0xea, 0xd8, 0x9e, 0x02, 0xb8, 0x3b, 0x0f, 0xee, 0xc4, + 0x65, 0xb4, 0x29, 0xe4, 0xda, 0xee, 0x62, 0xdf, 0xce, 0xc7, 0x15, 0xb0, 0x6a, 0x25, 0xe1, 0x57, + 0x1f, 0xac, 0xd7, 0xec, 0x00, 0x6e, 0xe3, 0xaa, 0x67, 0x70, 0x83, 0xe5, 0x06, 0xf7, 0x97, 0x2f, + 0x2c, 0x07, 0x0d, 0xef, 0xbe, 0xff, 0xf6, 0xfb, 0xf3, 0x29, 0x0c, 0x6f, 0x91, 0xb6, 0x58, 0x74, + 0xb3, 0xdd, 0xec, 0x4e, 0xf5, 0x1d, 0x34, 0xfc, 0xe0, 0x83, 0xd6, 0x7c, 0xa1, 0xf0, 0x46, 0xad, + 0xfa, 0xa2, 0x1b, 0x82, 0x9b, 0x4d, 0x52, 0x1d, 0xda, 0x96, 0x45, 0x43, 0x70, 0xf3, 0x18, 0xb4, + 0xb9, 0x0d, 0xe0, 0x17, 0x1f, 0xac, 0x55, 0xe6, 0x83, 0x51, 0xad, 0x4e, 0x9d, 0x5d, 0x82, 0xce, + 0x32, 0x25, 0x0e, 0x71, 0xdb, 0x22, 0x46, 0x90, 0x1c, 0x83, 0x58, 0x7d, 0x37, 0xf2, 0xd6, 0x19, + 0xf0, 0x5d, 0xf7, 0xc9, 0xf8, 0x17, 0xf2, 0xc6, 0x13, 0xe4, 0x1f, 0x4d, 0x90, 0xff, 0x73, 0x82, + 0xfc, 0x4f, 0x53, 0xe4, 0x1d, 0x4d, 0x91, 0xf7, 0x7d, 0x8a, 0xbc, 0x97, 0x58, 0x24, 0x66, 0x6f, + 0x18, 0x63, 0xa6, 0x06, 0xa4, 0x2d, 0x52, 0x1a, 0x6b, 0xd2, 0x16, 0xb7, 0xd9, 0x1e, 0x4d, 0x24, + 0x79, 0xf3, 0x9f, 0x8e, 0x39, 0xc8, 0xb8, 0x8e, 0x4f, 0xdb, 0x3f, 0xc1, 0x9d, 0x3f, 0x01, 0x00, + 0x00, 0xff, 0xff, 0xb3, 0xb3, 0x06, 0x02, 0x93, 0x04, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// QueryClient is the client API for Query service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type QueryClient interface { + // TotalFractionalBalances returns the total sum of all fractional balances + // managed by the precisebank module. + TotalFractionalBalances(ctx context.Context, in *QueryTotalFractionalBalancesRequest, opts ...grpc.CallOption) (*QueryTotalFractionalBalancesResponse, error) + // Remainder returns the amount backed by the reserve, but not yet owned by + // any account, i.e. not in circulation. + Remainder(ctx context.Context, in *QueryRemainderRequest, opts ...grpc.CallOption) (*QueryRemainderResponse, error) + // FractionalBalance returns only the fractional balance of an address. This + // does not include any integer balance. + FractionalBalance(ctx context.Context, in *QueryFractionalBalanceRequest, opts ...grpc.CallOption) (*QueryFractionalBalanceResponse, error) +} + +type queryClient struct { + cc grpc1.ClientConn +} + +func NewQueryClient(cc grpc1.ClientConn) QueryClient { + return &queryClient{cc} +} + +func (c *queryClient) TotalFractionalBalances(ctx context.Context, in *QueryTotalFractionalBalancesRequest, opts ...grpc.CallOption) (*QueryTotalFractionalBalancesResponse, error) { + out := new(QueryTotalFractionalBalancesResponse) + err := c.cc.Invoke(ctx, "/zgc.precisebank.v1.Query/TotalFractionalBalances", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) Remainder(ctx context.Context, in *QueryRemainderRequest, opts ...grpc.CallOption) (*QueryRemainderResponse, error) { + out := new(QueryRemainderResponse) + err := c.cc.Invoke(ctx, "/zgc.precisebank.v1.Query/Remainder", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) FractionalBalance(ctx context.Context, in *QueryFractionalBalanceRequest, opts ...grpc.CallOption) (*QueryFractionalBalanceResponse, error) { + out := new(QueryFractionalBalanceResponse) + err := c.cc.Invoke(ctx, "/zgc.precisebank.v1.Query/FractionalBalance", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// QueryServer is the server API for Query service. +type QueryServer interface { + // TotalFractionalBalances returns the total sum of all fractional balances + // managed by the precisebank module. + TotalFractionalBalances(context.Context, *QueryTotalFractionalBalancesRequest) (*QueryTotalFractionalBalancesResponse, error) + // Remainder returns the amount backed by the reserve, but not yet owned by + // any account, i.e. not in circulation. + Remainder(context.Context, *QueryRemainderRequest) (*QueryRemainderResponse, error) + // FractionalBalance returns only the fractional balance of an address. This + // does not include any integer balance. + FractionalBalance(context.Context, *QueryFractionalBalanceRequest) (*QueryFractionalBalanceResponse, error) +} + +// UnimplementedQueryServer can be embedded to have forward compatible implementations. +type UnimplementedQueryServer struct { +} + +func (*UnimplementedQueryServer) TotalFractionalBalances(ctx context.Context, req *QueryTotalFractionalBalancesRequest) (*QueryTotalFractionalBalancesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method TotalFractionalBalances not implemented") +} +func (*UnimplementedQueryServer) Remainder(ctx context.Context, req *QueryRemainderRequest) (*QueryRemainderResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Remainder not implemented") +} +func (*UnimplementedQueryServer) FractionalBalance(ctx context.Context, req *QueryFractionalBalanceRequest) (*QueryFractionalBalanceResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method FractionalBalance not implemented") +} + +func RegisterQueryServer(s grpc1.Server, srv QueryServer) { + s.RegisterService(&_Query_serviceDesc, srv) +} + +func _Query_TotalFractionalBalances_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryTotalFractionalBalancesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).TotalFractionalBalances(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.precisebank.v1.Query/TotalFractionalBalances", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).TotalFractionalBalances(ctx, req.(*QueryTotalFractionalBalancesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_Remainder_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryRemainderRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Remainder(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.precisebank.v1.Query/Remainder", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Remainder(ctx, req.(*QueryRemainderRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_FractionalBalance_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryFractionalBalanceRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).FractionalBalance(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.precisebank.v1.Query/FractionalBalance", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).FractionalBalance(ctx, req.(*QueryFractionalBalanceRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Query_serviceDesc = grpc.ServiceDesc{ + ServiceName: "zgc.precisebank.v1.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "TotalFractionalBalances", + Handler: _Query_TotalFractionalBalances_Handler, + }, + { + MethodName: "Remainder", + Handler: _Query_Remainder_Handler, + }, + { + MethodName: "FractionalBalance", + Handler: _Query_FractionalBalance_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "zgc/precisebank/v1/query.proto", +} + +func (m *QueryTotalFractionalBalancesRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryTotalFractionalBalancesRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryTotalFractionalBalancesRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryTotalFractionalBalancesResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryTotalFractionalBalancesResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryTotalFractionalBalancesResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Total.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *QueryRemainderRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryRemainderRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryRemainderRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryRemainderResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryRemainderResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryRemainderResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Remainder.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *QueryFractionalBalanceRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryFractionalBalanceRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryFractionalBalanceRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryFractionalBalanceResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryFractionalBalanceResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryFractionalBalanceResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.FractionalBalance.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { + offset -= sovQuery(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *QueryTotalFractionalBalancesRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryTotalFractionalBalancesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Total.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *QueryRemainderRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryRemainderResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Remainder.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *QueryFractionalBalanceRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryFractionalBalanceResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.FractionalBalance.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func sovQuery(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozQuery(x uint64) (n int) { + return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *QueryTotalFractionalBalancesRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryTotalFractionalBalancesRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryTotalFractionalBalancesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryTotalFractionalBalancesResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryTotalFractionalBalancesResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryTotalFractionalBalancesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Total", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Total.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryRemainderRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryRemainderRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryRemainderRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryRemainderResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryRemainderResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryRemainderResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Remainder", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Remainder.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryFractionalBalanceRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryFractionalBalanceRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryFractionalBalanceRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryFractionalBalanceResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryFractionalBalanceResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryFractionalBalanceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FractionalBalance", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.FractionalBalance.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipQuery(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthQuery + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupQuery + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthQuery + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthQuery = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowQuery = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupQuery = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/precisebank/types/query.pb.gw.go b/x/precisebank/types/query.pb.gw.go new file mode 100644 index 00000000..74cce9be --- /dev/null +++ b/x/precisebank/types/query.pb.gw.go @@ -0,0 +1,319 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: zgc/precisebank/v1/query.proto + +/* +Package types is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package types + +import ( + "context" + "io" + "net/http" + + "github.com/golang/protobuf/descriptor" + "github.com/golang/protobuf/proto" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/grpc-ecosystem/grpc-gateway/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" +) + +// Suppress "imported and not used" errors +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage +var _ = metadata.Join + +func request_Query_TotalFractionalBalances_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryTotalFractionalBalancesRequest + var metadata runtime.ServerMetadata + + msg, err := client.TotalFractionalBalances(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_TotalFractionalBalances_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryTotalFractionalBalancesRequest + var metadata runtime.ServerMetadata + + msg, err := server.TotalFractionalBalances(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_Remainder_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryRemainderRequest + var metadata runtime.ServerMetadata + + msg, err := client.Remainder(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Remainder_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryRemainderRequest + var metadata runtime.ServerMetadata + + msg, err := server.Remainder(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_FractionalBalance_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryFractionalBalanceRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["address"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "address") + } + + protoReq.Address, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "address", err) + } + + msg, err := client.FractionalBalance(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_FractionalBalance_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryFractionalBalanceRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["address"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "address") + } + + protoReq.Address, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "address", err) + } + + msg, err := server.FractionalBalance(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_TotalFractionalBalances_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_TotalFractionalBalances_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_TotalFractionalBalances_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Remainder_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Remainder_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Remainder_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_FractionalBalance_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_FractionalBalance_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_FractionalBalance_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.Dial(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + + return RegisterQueryHandler(ctx, mux, conn) +} + +// RegisterQueryHandler registers the http handlers for service Query to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn)) +} + +// RegisterQueryHandlerClient registers the http handlers for service Query +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "QueryClient" to call the correct interceptors. +func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error { + + mux.Handle("GET", pattern_Query_TotalFractionalBalances_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_TotalFractionalBalances_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_TotalFractionalBalances_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Remainder_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_Remainder_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Remainder_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_FractionalBalance_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_FractionalBalance_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_FractionalBalance_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_Query_TotalFractionalBalances_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"0g", "precisebank", "v1", "total_fractional_balances"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_Remainder_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"0g", "precisebank", "v1", "remainder"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_FractionalBalance_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"0g", "precisebank", "v1", "fractional_balance", "address"}, "", runtime.AssumeColonVerbOpt(true))) +) + +var ( + forward_Query_TotalFractionalBalances_0 = runtime.ForwardResponseMessage + + forward_Query_Remainder_0 = runtime.ForwardResponseMessage + + forward_Query_FractionalBalance_0 = runtime.ForwardResponseMessage +) diff --git a/x/pricefeed/abci.go b/x/pricefeed/abci.go index f590f497..a1ad752f 100644 --- a/x/pricefeed/abci.go +++ b/x/pricefeed/abci.go @@ -1,7 +1,6 @@ package pricefeed import ( - "errors" "time" "github.com/0glabs/0g-chain/x/pricefeed/keeper" @@ -14,15 +13,5 @@ import ( func EndBlocker(ctx sdk.Context, k keeper.Keeper) { defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyEndBlocker) - // Update the current price of each asset. - for _, market := range k.GetMarkets(ctx) { - if !market.Active { - continue - } - - err := k.SetCurrentPrices(ctx, market.MarketID) - if err != nil && !errors.Is(err, types.ErrNoValidPrice) { - panic(err) - } - } + k.SetCurrentPricesForAllMarkets(ctx) } diff --git a/x/pricefeed/abci_test.go b/x/pricefeed/abci_test.go new file mode 100644 index 00000000..9de40a55 --- /dev/null +++ b/x/pricefeed/abci_test.go @@ -0,0 +1,20 @@ +package pricefeed_test + +import ( + "testing" + + "github.com/0glabs/0g-chain/x/pricefeed" + "github.com/0glabs/0g-chain/x/pricefeed/keeper" + "github.com/0glabs/0g-chain/x/pricefeed/testutil" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func TestEndBlocker_UpdatesMultipleMarkets(t *testing.T) { + testutil.SetCurrentPrices_PriceCalculations(t, func(ctx sdk.Context, keeper keeper.Keeper) { + pricefeed.EndBlocker(ctx, keeper) + }) + + testutil.SetCurrentPrices_EventEmission(t, func(ctx sdk.Context, keeper keeper.Keeper) { + pricefeed.EndBlocker(ctx, keeper) + }) +} diff --git a/x/pricefeed/keeper/keeper.go b/x/pricefeed/keeper/keeper.go index a99cdd1c..7bd0a700 100644 --- a/x/pricefeed/keeper/keeper.go +++ b/x/pricefeed/keeper/keeper.go @@ -131,6 +131,74 @@ func (k Keeper) SetCurrentPrices(ctx sdk.Context, marketID string) error { return nil } +// SetCurrentPricesForAllMarkets updates the price of an asset to the median of all valid oracle inputs +func (k Keeper) SetCurrentPricesForAllMarkets(ctx sdk.Context) { + orderedMarkets := []string{} + marketPricesByID := make(map[string]types.CurrentPrices) + + for _, market := range k.GetMarkets(ctx) { + if market.Active { + orderedMarkets = append(orderedMarkets, market.MarketID) + marketPricesByID[market.MarketID] = types.CurrentPrices{} + } + } + + iterator := sdk.KVStorePrefixIterator(ctx.KVStore(k.key), types.RawPriceFeedPrefix) + for ; iterator.Valid(); iterator.Next() { + var postedPrice types.PostedPrice + k.cdc.MustUnmarshal(iterator.Value(), &postedPrice) + + prices, found := marketPricesByID[postedPrice.MarketID] + if !found { + continue + } + + // filter out expired prices + if postedPrice.Expiry.After(ctx.BlockTime()) { + marketPricesByID[postedPrice.MarketID] = append(prices, types.NewCurrentPrice(postedPrice.MarketID, postedPrice.Price)) + } + } + iterator.Close() + + for _, marketID := range orderedMarkets { + // store current price + validPrevPrice := true + prevPrice, err := k.GetCurrentPrice(ctx, marketID) + if err != nil { + validPrevPrice = false + } + + notExpiredPrices, _ := marketPricesByID[marketID] + + if len(notExpiredPrices) == 0 { + // NOTE: The current price stored will continue storing the most recent (expired) + // price if this is not set. + // This zero's out the current price stored value for that market and ensures + // that CDP methods that GetCurrentPrice will return error. + k.setCurrentPrice(ctx, marketID, types.CurrentPrice{}) + continue + } + + medianPrice := k.CalculateMedianPrice(notExpiredPrices) + + // check case that market price was not set in genesis + //if validPrevPrice && !medianPrice.Equal(prevPrice.Price) { + if validPrevPrice && !medianPrice.Equal(prevPrice.Price) { + // only emit event if price has changed + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeMarketPriceUpdated, + sdk.NewAttribute(types.AttributeMarketID, marketID), + sdk.NewAttribute(types.AttributeMarketPrice, medianPrice.String()), + ), + ) + } + + currentPrice := types.NewCurrentPrice(marketID, medianPrice) + k.setCurrentPrice(ctx, marketID, currentPrice) + } +} + func (k Keeper) setCurrentPrice(ctx sdk.Context, marketID string, currentPrice types.CurrentPrice) { store := ctx.KVStore(k.key) store.Set(types.CurrentPriceKey(marketID), k.cdc.MustMarshal(¤tPrice)) diff --git a/x/pricefeed/keeper/keeper_test.go b/x/pricefeed/keeper/keeper_test.go index 9a2dc138..959a636c 100644 --- a/x/pricefeed/keeper/keeper_test.go +++ b/x/pricefeed/keeper/keeper_test.go @@ -1,6 +1,7 @@ package keeper_test import ( + "errors" "testing" "time" @@ -11,6 +12,8 @@ import ( tmprototypes "github.com/cometbft/cometbft/proto/tendermint/types" "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/pricefeed/keeper" + "github.com/0glabs/0g-chain/x/pricefeed/testutil" "github.com/0glabs/0g-chain/x/pricefeed/types" ) @@ -236,3 +239,33 @@ func TestKeeper_ExpiredSetCurrentPrices(t *testing.T) { _, err = keeper.GetCurrentPrice(ctx, "tstusd") require.ErrorIs(t, types.ErrNoValidPrice, err, "current prices should be invalid") } + +func TestKeeper_SetCurrentPricesForAllMarkets_PriceUpdate(t *testing.T) { + testutil.SetCurrentPrices_PriceCalculations(t, func(ctx sdk.Context, keeper keeper.Keeper) { + keeper.SetCurrentPricesForAllMarkets(ctx) + }) +} + +func TestKeeper_SetCurrentPricesForAllMarkets_EventEmission(t *testing.T) { + testutil.SetCurrentPrices_EventEmission(t, func(ctx sdk.Context, keeper keeper.Keeper) { + keeper.SetCurrentPricesForAllMarkets(ctx) + }) +} + +func TestKeeper_SetCurrentPrices_MatchesAllMarketsBehavior(t *testing.T) { + testFunc := func(ctx sdk.Context, k keeper.Keeper) { + for _, market := range k.GetMarkets(ctx) { + if !market.Active { + continue + } + + err := k.SetCurrentPrices(ctx, market.MarketID) + if err != nil && !errors.Is(err, types.ErrNoValidPrice) { + panic(err) + } + } + } + + testutil.SetCurrentPrices_PriceCalculations(t, testFunc) + testutil.SetCurrentPrices_EventEmission(t, testFunc) +} diff --git a/x/pricefeed/testutil/helpers.go b/x/pricefeed/testutil/helpers.go new file mode 100644 index 00000000..5c1465eb --- /dev/null +++ b/x/pricefeed/testutil/helpers.go @@ -0,0 +1,236 @@ +package testutil + +import ( + "testing" + "time" + + tmprototypes "github.com/cometbft/cometbft/proto/tendermint/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/pricefeed/keeper" + "github.com/0glabs/0g-chain/x/pricefeed/types" +) + +func SetCurrentPrices_PriceCalculations(t *testing.T, f func(ctx sdk.Context, keeper keeper.Keeper)) { + _, addrs := app.GeneratePrivKeyAddressPairs(5) + tApp := app.NewTestApp() + ctx := tApp.NewContext(true, tmprototypes.Header{}). + WithBlockTime(time.Now().UTC()) + keeper := tApp.GetPriceFeedKeeper() + + params := types.Params{ + Markets: []types.Market{ + // valid previous price, expired prices, price change, and active + {MarketID: "asset1:usd", BaseAsset: "asset1", QuoteAsset: "usd", Oracles: addrs, Active: true}, + // same data as asset1, but not active and should be ignored + {MarketID: "asset2:usd", BaseAsset: "asset2", QuoteAsset: "usd", Oracles: addrs, Active: false}, + // same data as asset1 except no valid previous price + {MarketID: "asset3:usd", BaseAsset: "asset3", QuoteAsset: "usd", Oracles: addrs, Active: true}, + // previous price set, but no valid prices + {MarketID: "asset4:usd", BaseAsset: "asset4", QuoteAsset: "usd", Oracles: addrs, Active: true}, + // same as market one except different prices + {MarketID: "asset5:usd", BaseAsset: "asset5", QuoteAsset: "usd", Oracles: addrs, Active: true}, + }, + } + keeper.SetParams(ctx, params) + + // need price equal to block time and after block time + blockTime := time.Now() + initialPriceExpiry := blockTime.Add(1 * time.Hour) + + _, err := keeper.SetPrice(ctx, addrs[0], "asset1:usd", sdk.MustNewDecFromStr("1"), initialPriceExpiry) + require.NoError(t, err) + _, err = keeper.SetPrice(ctx, addrs[0], "asset2:usd", sdk.MustNewDecFromStr("1"), initialPriceExpiry) + require.NoError(t, err) + _, err = keeper.SetPrice(ctx, addrs[0], "asset4:usd", sdk.MustNewDecFromStr("1"), initialPriceExpiry) + require.NoError(t, err) + _, err = keeper.SetPrice(ctx, addrs[0], "asset5:usd", sdk.MustNewDecFromStr("10"), initialPriceExpiry) + require.NoError(t, err) + + ctx = ctx.WithBlockTime(blockTime) + f(ctx, keeper) + + // price should be set + price, err := keeper.GetCurrentPrice(ctx, "asset1:usd") + require.NoError(t, err) + require.Equal(t, sdk.OneDec(), price.Price) + // not an active market, so price is not set + price, err = keeper.GetCurrentPrice(ctx, "asset2:usd") + require.Equal(t, types.ErrNoValidPrice, err) + // no price posted + price, err = keeper.GetCurrentPrice(ctx, "asset3:usd") + require.Equal(t, types.ErrNoValidPrice, err) + // price set initially + price, err = keeper.GetCurrentPrice(ctx, "asset4:usd") + require.NoError(t, err) + require.Equal(t, sdk.OneDec(), price.Price) + price, err = keeper.GetCurrentPrice(ctx, "asset5:usd") + require.NoError(t, err) + require.Equal(t, sdk.MustNewDecFromStr("10.0"), price.Price) + + _, err = keeper.SetPrice(ctx, addrs[1], "asset1:usd", sdk.MustNewDecFromStr("2"), initialPriceExpiry.Add(1*time.Hour)) + require.NoError(t, err) + _, err = keeper.SetPrice(ctx, addrs[1], "asset2:usd", sdk.MustNewDecFromStr("2"), initialPriceExpiry.Add(1*time.Hour)) + require.NoError(t, err) + _, err = keeper.SetPrice(ctx, addrs[1], "asset5:usd", sdk.MustNewDecFromStr("20"), initialPriceExpiry.Add(1*time.Hour)) + require.NoError(t, err) + + blockTime = blockTime.Add(30 * time.Minute) + ctx = ctx.WithBlockTime(blockTime) + f(ctx, keeper) + + // price should be set + price, err = keeper.GetCurrentPrice(ctx, "asset1:usd") + require.NoError(t, err) + require.Equal(t, sdk.MustNewDecFromStr("1.5"), price.Price) + // not an active market, so price is not set + price, err = keeper.GetCurrentPrice(ctx, "asset2:usd") + require.Equal(t, types.ErrNoValidPrice, err) + // no price posted + price, err = keeper.GetCurrentPrice(ctx, "asset3:usd") + require.Equal(t, types.ErrNoValidPrice, err) + // price set initially + price, err = keeper.GetCurrentPrice(ctx, "asset4:usd") + require.NoError(t, err) + require.Equal(t, sdk.OneDec(), price.Price) + price, err = keeper.GetCurrentPrice(ctx, "asset5:usd") + require.NoError(t, err) + require.Equal(t, sdk.MustNewDecFromStr("15.0"), price.Price) + + _, err = keeper.SetPrice(ctx, addrs[2], "asset1:usd", sdk.MustNewDecFromStr("30"), initialPriceExpiry.Add(1*time.Hour)) + require.NoError(t, err) + _, err = keeper.SetPrice(ctx, addrs[2], "asset2:usd", sdk.MustNewDecFromStr("30"), initialPriceExpiry.Add(1*time.Hour)) + require.NoError(t, err) + _, err = keeper.SetPrice(ctx, addrs[2], "asset5:usd", sdk.MustNewDecFromStr("30"), initialPriceExpiry.Add(1*time.Hour)) + require.NoError(t, err) + + blockTime = blockTime.Add(15 * time.Minute) + ctx = ctx.WithBlockTime(blockTime) + f(ctx, keeper) + + // price should be set + price, err = keeper.GetCurrentPrice(ctx, "asset1:usd") + require.NoError(t, err) + require.Equal(t, sdk.MustNewDecFromStr("2.0"), price.Price) + // not an active market, so price is not set + price, err = keeper.GetCurrentPrice(ctx, "asset2:usd") + require.Equal(t, types.ErrNoValidPrice, err) + // no price posted + price, err = keeper.GetCurrentPrice(ctx, "asset3:usd") + require.Equal(t, types.ErrNoValidPrice, err) + // price set initially + price, err = keeper.GetCurrentPrice(ctx, "asset4:usd") + require.NoError(t, err) + require.Equal(t, sdk.OneDec(), price.Price) + price, err = keeper.GetCurrentPrice(ctx, "asset5:usd") + require.NoError(t, err) + require.Equal(t, sdk.MustNewDecFromStr("20.0"), price.Price) + + blockTime = blockTime.Add(15 * time.Minute) + ctx = ctx.WithBlockTime(blockTime) + f(ctx, keeper) + + // price should be set + price, err = keeper.GetCurrentPrice(ctx, "asset1:usd") + require.NoError(t, err) + require.Equal(t, sdk.MustNewDecFromStr("16"), price.Price) + // not an active market, so price is not set + price, err = keeper.GetCurrentPrice(ctx, "asset2:usd") + require.Equal(t, types.ErrNoValidPrice, err) + // no price posted + price, err = keeper.GetCurrentPrice(ctx, "asset3:usd") + require.Equal(t, types.ErrNoValidPrice, err) + // price set initially, now expired + price, err = keeper.GetCurrentPrice(ctx, "asset4:usd") + require.Equal(t, types.ErrNoValidPrice, err) + price, err = keeper.GetCurrentPrice(ctx, "asset5:usd") + require.NoError(t, err) + require.Equal(t, sdk.MustNewDecFromStr("25.0"), price.Price) + + blockTime = blockTime.Add(10 * time.Hour) + ctx = ctx.WithBlockTime(blockTime) + f(ctx, keeper) + + // all prices expired now + price, err = keeper.GetCurrentPrice(ctx, "asset1:usd") + require.Equal(t, types.ErrNoValidPrice, err) + price, err = keeper.GetCurrentPrice(ctx, "asset2:usd") + require.Equal(t, types.ErrNoValidPrice, err) + price, err = keeper.GetCurrentPrice(ctx, "asset3:usd") + require.Equal(t, types.ErrNoValidPrice, err) + price, err = keeper.GetCurrentPrice(ctx, "asset4:usd") + require.Equal(t, types.ErrNoValidPrice, err) + price, err = keeper.GetCurrentPrice(ctx, "asset5:usd") + require.Equal(t, types.ErrNoValidPrice, err) +} + +func SetCurrentPrices_EventEmission(t *testing.T, f func(ctx sdk.Context, keeper keeper.Keeper)) { + _, addrs := app.GeneratePrivKeyAddressPairs(5) + tApp := app.NewTestApp() + ctx := tApp.NewContext(true, tmprototypes.Header{}). + WithBlockTime(time.Now().UTC()) + keeper := tApp.GetPriceFeedKeeper() + + params := types.Params{ + Markets: []types.Market{ + {MarketID: "asset1:usd", BaseAsset: "asset1", QuoteAsset: "usd", Oracles: addrs, Active: true}, + }, + } + keeper.SetParams(ctx, params) + + blockTime := time.Now() + initialPriceExpiry := blockTime.Add(1 * time.Hour) + + // post a price + _, err := keeper.SetPrice(ctx, addrs[0], "asset1:usd", sdk.MustNewDecFromStr("1"), initialPriceExpiry) + require.NoError(t, err) + + // reset context with fresh event manager + ctx = ctx.WithBlockTime(blockTime).WithEventManager(sdk.NewEventManager()) + f(ctx, keeper) + + // no previous price so no event + require.Equal(t, 0, len(ctx.EventManager().Events())) + + // post same price from another oracle + _, err = keeper.SetPrice(ctx, addrs[1], "asset1:usd", sdk.MustNewDecFromStr("1"), initialPriceExpiry) + require.NoError(t, err) + + blockTime = blockTime.Add(10 * time.Second) + ctx = ctx.WithBlockTime(blockTime).WithEventManager(sdk.NewEventManager()) + f(ctx, keeper) + + // no price change so no event + require.Equal(t, 0, len(ctx.EventManager().Events())) + + // post price changes + _, err = keeper.SetPrice(ctx, addrs[2], "asset1:usd", sdk.MustNewDecFromStr("2"), initialPriceExpiry) + require.NoError(t, err) + _, err = keeper.SetPrice(ctx, addrs[3], "asset1:usd", sdk.MustNewDecFromStr("10"), initialPriceExpiry) + require.NoError(t, err) + _, err = keeper.SetPrice(ctx, addrs[4], "asset1:usd", sdk.MustNewDecFromStr("10"), initialPriceExpiry) + require.NoError(t, err) + + blockTime = blockTime.Add(10 * time.Second) + ctx = ctx.WithBlockTime(blockTime).WithEventManager(sdk.NewEventManager()) + f(ctx, keeper) + + // price is changes so event should be emitted + require.Equal(t, 1, len(ctx.EventManager().Events())) + + event := ctx.EventManager().Events()[0] + + // has correct event type + assert.Equal(t, types.EventTypeMarketPriceUpdated, event.Type) + // has correct attributes + marketID, found := event.GetAttribute(types.AttributeMarketID) + require.True(t, found) + marketPrice, found := event.GetAttribute(types.AttributeMarketPrice) + require.True(t, found) + // attributes have correct values + assert.Equal(t, "asset1:usd", marketID.Value) + assert.Equal(t, sdk.MustNewDecFromStr("2").String(), marketPrice.Value) +}