diff --git a/.env.example b/.env.example index 16d79a745..8114ea82d 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,6 @@ -# Which type of ethereum testnet to run locally (anvil|pos) +# Which type of ethereum testnet to run locally (anvil|pos|besu-qbft|none) +# Validated Besu mode for e2e: ETH_TESTNET_TYPE=besu-qbft, ETH_LC_ON_COSMOS=attestor-native, +# COSMOS_LC_ON_ETH=sp1, SP1_PROVER=mock ETH_TESTNET_TYPE="anvil" # Preset for Ethereum PoS network configuration (minimal|mainnet) ETHEREUM_POS_NETWORK_PRESET="minimal" diff --git a/.github/workflows/abigen.yaml b/.github/workflows/abigen.yaml index b9a942eeb..1d3f1b4f2 100644 --- a/.github/workflows/abigen.yaml +++ b/.github/workflows/abigen.yaml @@ -9,7 +9,9 @@ on: pull_request: paths: - 'ibc-solidity/abi/**' + - 'ibc-solidity/solidity.just' - 'packages/go-abigen/**' + - 'e2e/interchaintestv8/types/erc20/**' - '**.sol' - 'ibc-solidity/bun.lock' push: @@ -17,7 +19,11 @@ on: - main paths: - 'ibc-solidity/abi/**' + - 'ibc-solidity/solidity.just' - 'packages/go-abigen/**' + - 'e2e/interchaintestv8/types/erc20/**' + - '**.sol' + - 'ibc-solidity/bun.lock' jobs: check: @@ -38,16 +44,18 @@ jobs: - name: Install abigen run: go install github.com/ethereum/go-ethereum/cmd/abigen@be4dc0c4be2fe316dbdd0a73e48421f64978232f # v1.17.2 - - name: Run abigen + - name: Generate contract artifacts run: just solidity::generate-abi - - name: Check for diffs in go-abigen + - name: Check generated contract artifacts run: | - if ! git diff --quiet HEAD -- packages/go-abigen; then - echo "Git diff found in the selected directory. Failing the job." + if [ -n "$(git status --short --untracked-files=all -- ibc-solidity/abi packages/go-abigen e2e/interchaintestv8/types/erc20)" ]; then + echo "Generated contract artifacts are stale." + git status --short --untracked-files=all -- ibc-solidity/abi packages/go-abigen e2e/interchaintestv8/types/erc20 + git diff --stat -- ibc-solidity/abi packages/go-abigen e2e/interchaintestv8/types/erc20 exit 1 else - echo "No changes detected in the selected directory." + echo "Generated contract artifacts are current." fi golangci: diff --git a/.github/workflows/e2e-attestor.yml b/.github/workflows/e2e-attestor.yml index 40d4f5be8..34655d294 100644 --- a/.github/workflows/e2e-attestor.yml +++ b/.github/workflows/e2e-attestor.yml @@ -104,7 +104,6 @@ jobs: fail-fast: false matrix: ${{ fromJson(needs.generate-matrix-eth-to-eth.outputs.matrix) }} name: attestor-native/${{ matrix.entrypoint }}/${{ matrix.test }} - runs-on: depot-ubuntu-24.04-4 permissions: contents: read @@ -121,6 +120,52 @@ jobs: cd e2e/interchaintestv8 go test -v -mod=readonly . -run "^${{ matrix.entrypoint }}$/${{ matrix.test }}$" -timeout 60m + e2e-besu-qbft: + needs: build-e2e-programs + name: besu-qbft/ics20-roundtrip + env: + ETH_TESTNET_TYPE: besu-qbft + ETH_LC_ON_COSMOS: attestor-native + COSMOS_LC_ON_ETH: sp1 + SP1_PROVER: mock + E2E_PROOF_TYPE: groth16 + runs-on: depot-ubuntu-24.04-4 + permissions: + contents: read + packages: read + steps: + - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0 + - name: Set up E2E environment + uses: ./.github/actions/e2e-setup + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + - name: Run test + run: | + cd e2e/interchaintestv8 + go test -v -mod=readonly . -run '^TestWithIbcEurekaTestSuite$/^Test_ICS20TransferERC20TokenfromEthereumToCosmosAndBack$' -timeout 60m + + e2e-besu-to-besu: + needs: build-e2e-programs + name: besu-to-besu + runs-on: depot-ubuntu-24.04-4 + permissions: + contents: read + packages: read + steps: + - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0 + - name: Set up E2E environment + uses: ./.github/actions/e2e-setup + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + - name: Run Go package tests + run: | + cd e2e/interchaintestv8 + go test ./e2esuite + - name: Run Besu to Besu test suite + run: | + cd e2e/interchaintestv8 + go test -v -mod=readonly . -run '^TestWithBesuToBesuTestSuite$' -timeout 60m + e2e-multi-attestor-native: needs: build-e2e-programs strategy: diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..d49ff44e6 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,23 @@ +# AGENTS.md + +This repo combines Solidity/Foundry contracts, a Rust workspace, Solana Anchor programs, and Go-based end-to-end tooling for IBC Eureka. + +Look here first: +- `README.md` +- `justfile` +- `ibc-solidity/foundry.toml` +- `Cargo.toml` +- `ibc-solidity/contracts/README.md` + +Use the smallest relevant validation from the repo root: +- Solidity: `just solidity::lint-solidity` and `just solidity::test-foundry` +- Rust workspace, relayer, operator, and shared packages: `just lint-rust` and `just test-cargo` +- Broad cross-stack changes: `just lint` +- Solana or e2e changes: use the subtree-specific commands in `ibc-solana/AGENTS.md` or `e2e/interchaintestv8/AGENTS.md` + +Hard constraints: +- Do not hand-edit generated outputs in `packages/go-abigen/`, most of `packages/go-anchor/`, `e2e/interchaintestv8/solana/go-anchor/`, or protobuf outputs under `e2e/interchaintestv8/types/`; regenerate with `just solidity::generate-abi`, `just solana::generate-solana-types`, or `just generate-buf`. +- `packages/go-anchor/ics07_tendermint_patches/` is the hand-maintained exception inside `packages/go-anchor/`; preserve it across regeneration. +- If Solidity interfaces, ABI-exposed structs, or contract types change, run `just solidity::generate-abi` before validating Go or e2e code. +- If Solana program interfaces or IDLs change, run `just solana::generate-solana-types`. +- If `.proto` files change, run `just generate-buf`. diff --git a/Cargo.lock b/Cargo.lock index ba1c33d0e..32b9fb6b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8491,6 +8491,7 @@ dependencies = [ "opentelemetry-otlp", "opentelemetry_sdk", "prometheus", + "proof-api-besu-to-eth", "proof-api-core", "proof-api-cosmos-to-cosmos", "proof-api-cosmos-to-eth", @@ -8511,6 +8512,25 @@ dependencies = [ "warp", ] +[[package]] +name = "proof-api-besu-to-eth" +version = "0.1.0" +dependencies = [ + "alloy 2.0.4", + "alloy-rlp", + "anyhow", + "ethereum-apis 0.1.0", + "ethereum-light-client 0.1.0", + "ibc-eureka-solidity-types 0.1.0", + "proof-api-core", + "proof-api-lib", + "rlp 0.6.1", + "serde", + "serde_json", + "tonic 0.13.1", + "tracing", +] + [[package]] name = "proof-api-core" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index bb12b2295..092b37d8c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ members = [ "packages/proof-api/modules/eth-to-cosmos-compat", "packages/proof-api/modules/cosmos-to-eth", "packages/proof-api/modules/eth-to-eth", + "packages/proof-api/modules/besu-to-eth", "packages/proof-api/modules/cosmos-to-cosmos", "packages/proof-api/modules/solana-to-cosmos", "packages/proof-api/modules/cosmos-to-solana", @@ -60,6 +61,7 @@ proof-api-eth-to-cosmos = { path = "packages/proof-api/modules/eth-to-cos proof-api-eth-to-cosmos-compat = { path = "packages/proof-api/modules/eth-to-cosmos-compat", default-features = false } proof-api-cosmos-to-eth = { path = "packages/proof-api/modules/cosmos-to-eth", default-features = false } proof-api-eth-to-eth = { path = "packages/proof-api/modules/eth-to-eth", default-features = false } +proof-api-besu-to-eth = { path = "packages/proof-api/modules/besu-to-eth", default-features = false } proof-api-cosmos-to-cosmos = { path = "packages/proof-api/modules/cosmos-to-cosmos", default-features = false } proof-api-solana-to-cosmos = { path = "packages/proof-api/modules/solana-to-cosmos", default-features = false } proof-api-cosmos-to-solana = { path = "packages/proof-api/modules/cosmos-to-solana", default-features = false } diff --git a/README.md b/README.md index 97e659b46..fcada31d8 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,8 @@ This project is structured with the following directories: | `ICS26Router.sol` | IBC router handles sequencing, replay protection, and timeout checks. Passes proofs to light clients for verification, and resolves `portId` for app callbacks. Provable IBC storage is stored in this contract. | ✅ | | `ICS20Transfer.sol` | IBC transfer application to send and receive tokens to/from another IBC transfer implementation. | ✅ | | `SP1ICS07Tendermint.sol` | Tendermint light client powered by SP1. The entry point for SP1 proofs. | ✅ | +| `BesuIBFT2LightClient.sol` | Besu IBFT 2.0 light client for header-validator mode with weak-subjectivity updates and EVM proof verification, following the YUI + prover sealing-header verification model. | ✅ | +| `BesuQBFTLightClient.sol` | Besu QBFT light client for header-validator mode with weak-subjectivity updates and EVM proof verification, following the YUI + prover sealing-header verification model. | ✅ | | `ICS27GMP.sol` | IBC General Message Passing via Interchain Accounts. | ✅ | | `AttestationLightClient.sol` | The multisig contract implementing IBC Light Client specs. | ✅ | | `utils/IFTBaseUpgradeable.sol` | Interchain Fungible Token standard. Mint and burn alternative to ICS-20. | ⏳ | @@ -316,6 +318,7 @@ Note: These gas benchmarks are with Groth16. IBC is a peer-to-peer, light-client-based interoperability protocol. This repository contains the following light clients: - **SP1 Tendermint Light Client** – Verifies the consensus state of a Cosmos SDK chain powered by SP1 and `tendermint-rs`. (Solidity) +- **Besu IBFT 2.0 / QBFT Light Clients** – Verify Besu BFT headers in header-validator mode, track the counterparty `ICS26Router` account storage root, and verify EVM account/storage proofs for Eureka commitments. (Solidity) - [**Ethereum Light Client**](./ibc-solidity/programs/cw-ics08-wasm-eth/README.md) – Verifies the consensus state of the Ethereum chain. (CosmWasm) - **Attestation Light Client** – A multisig that can be used if the counterparty chain does not have a light client protocol. (Solidity and Solana) - **Solana Tendermint Light Client** - Verifies the consensus state of a Cosmos SDK chain powered by `tendermint-rs`. (Solana) diff --git a/e2e/interchaintestv8/AGENTS.md b/e2e/interchaintestv8/AGENTS.md new file mode 100644 index 000000000..4dac2d3e2 --- /dev/null +++ b/e2e/interchaintestv8/AGENTS.md @@ -0,0 +1,21 @@ +# AGENTS.md + +This subtree contains the Go end-to-end test suites that drive local Ethereum, Cosmos, and Solana environments through interchaintest. + +Look here first: +- `e2e/interchaintestv8/README.md` +- `e2e/interchaintestv8/go.mod` +- the relevant suite entrypoint (`ibc_eureka_test.go`, `relayer_test.go`, `sp1_ics07_test.go`, `solana_test.go`, etc.) + +Use the smallest relevant validation from the repo root: +- Single targeted test: `just test-e2e TestWithSuite/Test_Name` +- Common wrappers: `just test-e2e-eureka`, `just test-e2e-relayer`, `just test-e2e-cosmos-relayer`, `just test-e2e-sp1-ics07` +- Solana e2e wrappers: `just test-e2e-solana`, `just test-e2e-solana-gmp`, `just test-e2e-solana-ift`, `just test-e2e-solana-upgrade`, `just test-e2e-solana-attestation` +- Go lint for this subtree lives in `just lint-go`; see `justfile` for the other suite wrappers + +Local constraints: +- Prefer the smallest targeted test; full e2e runs are slow and environment-dependent. +- Local runs expect `.env` set up from `.env.example`; `just test-e2e` installs the relayer, and `just test-e2e-sp1-ics07` also installs the operator. +- If contract interfaces or ABI-exposed types change, run `just generate-abi` before e2e validation. +- If Solana IDLs change, run `just generate-solana-types`; if `.proto` files change, run `just generate-buf`. +- Do not hand-edit generated code under `e2e/interchaintestv8/types/` or `e2e/interchaintestv8/solana/go-anchor/`. diff --git a/e2e/interchaintestv8/README.md b/e2e/interchaintestv8/README.md index 17a01aed3..e68e017dd 100644 --- a/e2e/interchaintestv8/README.md +++ b/e2e/interchaintestv8/README.md @@ -8,6 +8,8 @@ These end to end tests are designed to run in the CI, but you can also run them ### Prerequisites +Besu tests additionally require Docker Compose v2 (`docker compose`). + In the repo root: ``` @@ -29,3 +31,65 @@ just test-e2e TestWithIbcEurekaTestSuite/Test_Deploy # Alternatively: just test-e2e-eureka Test_Deploy ``` + +## Besu QBFT mode + +Set `ETH_TESTNET_TYPE=besu-qbft` to start a real 4-validator Besu QBFT network. + +### Supported in this mode + +This pass supports the following Besu configuration: + +- `ETH_TESTNET_TYPE=besu-qbft` +- `ETH_LC_ON_COSMOS=attestor-native` +- `COSMOS_LC_ON_ETH=sp1` +- `SP1_PROVER=mock` + +Validated coverage in this mode: + +- Besu chain bring-up and contract deployment +- Dockerized Ethereum attestors reading Besu RPC +- relayer startup and client creation +- full Ethereum ↔ Cosmos ICS20 transfer roundtrip + +### Not supported + +- `ETH_LC_ON_COSMOS=full` +- beacon-chain-based Ethereum verification on Cosmos + +### Focused local test commands + +From the repo root, run: + +```shell +# Full ICS20 roundtrip in the supported Besu mode +ETH_TESTNET_TYPE=besu-qbft \ +ETH_LC_ON_COSMOS=attestor-native \ +COSMOS_LC_ON_ETH=sp1 \ +SP1_PROVER=mock \ +just test-e2e TestWithIbcEurekaTestSuite/Test_ICS20TransferERC20TokenfromEthereumToCosmosAndBack +``` + +## Focused Besu ↔ Besu e2e + +This focused suite starts two independent Besu QBFT networks, deploys Eureka contracts on both, starts the Rust relayer with `besu_to_eth` in both directions, deploys and registers Besu light clients on both chains, and verifies a one-way A → B ICS20 transfer plus the B → A acknowledgement relay using real Besu proofs. + +### Focused local test commands + +From the repo root, run: + +```shell +# Dual-Besu deploy / client-registration path +just test-e2e TestWithBesuToBesuTestSuite/Test_Deploy + +# One-way Besu A -> Besu B ICS20 transfer with acknowledgement relay back to A +just test-e2e TestWithBesuToBesuTestSuite/Test_ICS20TransferERC20FromChainAToChainB + +# Regenerate the QBFT light-client fixture used by test/besu-bft/* +GENERATE_BESU_LIGHT_CLIENT_FIXTURES=true \ +just test-e2e TestWithBesuToBesuTestSuite/Test_ICS20TransferERC20FromChainAToChainB +``` + +When `GENERATE_BESU_LIGHT_CLIENT_FIXTURES=true` is set, the focused Besu↔Besu transfer test writes: + +- `ibc-solidity/test/besu-bft/fixtures/qbft.json` diff --git a/e2e/interchaintestv8/attestor/setup.go b/e2e/interchaintestv8/attestor/setup.go index 9cf930e5b..08101c754 100644 --- a/e2e/interchaintestv8/attestor/setup.go +++ b/e2e/interchaintestv8/attestor/setup.go @@ -203,6 +203,7 @@ func SetupAttestors(ctx context.Context, t *testing.T, params SetupParams) Setup // chainType should be ChainTypeEvm for PoW chains or ChainTypeCosmos for PoS chains. func SetupEthAttestors(ctx context.Context, t *testing.T, client *dockerclient.Client, networkID, ethRPC, ics26Address string, chainType ChainType) SetupResult { t.Helper() + require.NotEmpty(t, ethRPC, "Ethereum attestors require a Docker-reachable Ethereum RPC URL") return SetupAttestors(ctx, t, SetupParams{ NumAttestors: testvalues.NumAttestors, KeystorePathTemplate: testvalues.AttestorKeystorePathTemplate, diff --git a/e2e/interchaintestv8/besu_to_besu_test.go b/e2e/interchaintestv8/besu_to_besu_test.go new file mode 100644 index 000000000..624fc140e --- /dev/null +++ b/e2e/interchaintestv8/besu_to_besu_test.go @@ -0,0 +1,511 @@ +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "context" + "crypto/ecdsa" + "fmt" + "math/big" + "os" + "path/filepath" + "strconv" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/suite" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + ethcommon "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + + transfertypes "github.com/cosmos/ibc-go/v11/modules/apps/transfer/types" + + "github.com/cosmos/solidity-ibc-eureka/packages/go-abigen/ibcerc20" + "github.com/cosmos/solidity-ibc-eureka/packages/go-abigen/ics20transfer" + "github.com/cosmos/solidity-ibc-eureka/packages/go-abigen/ics26router" + + "github.com/srdtrk/solidity-ibc-eureka/e2e/v8/chainconfig" + "github.com/srdtrk/solidity-ibc-eureka/e2e/v8/e2esuite" + "github.com/srdtrk/solidity-ibc-eureka/e2e/v8/ethereum" + "github.com/srdtrk/solidity-ibc-eureka/e2e/v8/proofapi" + "github.com/srdtrk/solidity-ibc-eureka/e2e/v8/testvalues" + e2etypes "github.com/srdtrk/solidity-ibc-eureka/e2e/v8/types" + "github.com/srdtrk/solidity-ibc-eureka/e2e/v8/types/erc20" + proofapitypes "github.com/srdtrk/solidity-ibc-eureka/e2e/v8/types/proofapi" +) + +const ( + besuToBesuChainBID = 1338 + + besuToBesuClientOnA = "besu-chain-b" + besuToBesuClientOnB = "besu-chain-a" + + besuToBesuConsensusTypeQBFT = "qbft" +) + +var besuToBesuChainBIPs = [4]string{"10.43.0.2", "10.43.0.3", "10.43.0.4", "10.43.0.5"} + +type besuToBesuChainState struct { + network chainconfig.BesuQBFTChain + eth ethereum.Ethereum + contractAddresses ethereum.DeployedContracts + ics26 *ics26router.Contract + ics20 *ics20transfer.Contract + erc20 *erc20.Contract + deployer *ecdsa.PrivateKey + user *ecdsa.PrivateKey + relayerSubmitter *ecdsa.PrivateKey + clientAddress ethcommon.Address +} + +type BesuToBesuTestSuite struct { + suite.Suite + + cwd string + relayerConfigPath string + relayerProcess *os.Process + relayerClient proofapitypes.ProofApiServiceClient + besuFixtureGenerator *e2etypes.BesuFixtureGenerator + + chainA besuToBesuChainState + chainB besuToBesuChainState +} + +func TestWithBesuToBesuTestSuite(t *testing.T) { + suite.Run(t, new(BesuToBesuTestSuite)) +} + +func (s *BesuToBesuTestSuite) SetupSuite() { + s.T().Cleanup(func() { + ctx := context.Background() + + if s.T() != nil && s.T().Failed() { + _ = s.chainA.network.DumpLogs(ctx) + _ = s.chainB.network.DumpLogs(ctx) + } + + if s.relayerProcess != nil { + _ = s.relayerProcess.Kill() + } + if s.relayerConfigPath != "" { + _ = os.Remove(s.relayerConfigPath) + } + + s.chainB.network.Destroy(ctx) + s.chainA.network.Destroy(ctx) + + if s.cwd != "" { + _ = os.Chdir(s.cwd) + } + }) + ctx := context.Background() + + if os.Getenv(testvalues.EnvKeyRustLog) == "" { + os.Setenv(testvalues.EnvKeyRustLog, testvalues.EnvValueRustLog_Info) + } + + var err error + s.cwd, err = os.Getwd() + s.Require().NoError(err) + s.Require().NoError(os.Chdir("../..")) + + s.chainA = s.spinUpChain(ctx, chainconfig.DefaultBesuQBFTParams()) + + s.chainB = s.spinUpChain(ctx, chainconfig.BesuQBFTParams{ + ChainID: besuToBesuChainBID, + Subnet: "10.43.0.0/16", + Gateway: "10.43.0.1", + ValidatorIPs: besuToBesuChainBIPs, + }) + s.Require().NoError(s.chainA.network.WaitForTransactionHandling(ctx)) + + s.besuFixtureGenerator = e2etypes.NewBesuFixtureGenerator() + + s.createUsers(&s.chainA) + s.createUsers(&s.chainB) + + s.deployContracts(&s.chainA) + s.deployContracts(&s.chainB) + + s.startRelayer() + s.connectRelayer() + + s.createAndRegisterBesuClient(&s.chainB, &s.chainA, besuToBesuClientOnA, besuToBesuClientOnB) + s.createAndRegisterBesuClient(&s.chainA, &s.chainB, besuToBesuClientOnB, besuToBesuClientOnA) +} + +func (s *BesuToBesuTestSuite) Test_Deploy() { + s.Require().True(s.Run("Verify ICS26 on Chain A", func() { + transferOnA, err := s.chainA.ics26.GetIBCApp(nil, transfertypes.PortID) + s.Require().NoError(err) + s.Require().Equal(strings.ToLower(s.chainA.contractAddresses.Ics20Transfer), strings.ToLower(transferOnA.Hex())) + })) + + s.Require().True(s.Run("Verify ICS26 on Chain B", func() { + transferOnB, err := s.chainB.ics26.GetIBCApp(nil, transfertypes.PortID) + s.Require().NoError(err) + s.Require().Equal(strings.ToLower(s.chainB.contractAddresses.Ics20Transfer), strings.ToLower(transferOnB.Hex())) + })) + + s.Require().True(s.Run("Verify Besu client on Chain A", func() { + clientOnA, err := s.chainA.ics26.GetClient(nil, besuToBesuClientOnA) + s.Require().NoError(err) + s.Require().Equal(s.chainA.clientAddress, clientOnA) + + counterparty, err := s.chainA.ics26.GetCounterparty(nil, besuToBesuClientOnA) + s.Require().NoError(err) + s.Require().Equal(besuToBesuClientOnB, counterparty.ClientId) + })) + + s.Require().True(s.Run("Verify Besu client on Chain B", func() { + clientOnB, err := s.chainB.ics26.GetClient(nil, besuToBesuClientOnB) + s.Require().NoError(err) + s.Require().Equal(s.chainB.clientAddress, clientOnB) + + counterparty, err := s.chainB.ics26.GetCounterparty(nil, besuToBesuClientOnB) + s.Require().NoError(err) + s.Require().Equal(besuToBesuClientOnA, counterparty.ClientId) + })) + + s.Require().True(s.Run("Verify Proof API Info A->B", func() { + info := s.waitForRelayerInfo(s.chainA.eth.ChainID.String(), s.chainB.eth.ChainID.String()) + s.Require().Equal(s.chainA.eth.ChainID.String(), info.SourceChain.ChainId) + s.Require().Equal(s.chainB.eth.ChainID.String(), info.TargetChain.ChainId) + })) + + s.Require().True(s.Run("Verify Proof API Info B->A", func() { + info := s.waitForRelayerInfo(s.chainB.eth.ChainID.String(), s.chainA.eth.ChainID.String()) + s.Require().Equal(s.chainB.eth.ChainID.String(), info.SourceChain.ChainId) + s.Require().Equal(s.chainA.eth.ChainID.String(), info.TargetChain.ChainId) + })) +} + +func (s *BesuToBesuTestSuite) Test_ICS20TransferERC20FromChainAToChainB() { + ctx := context.Background() + transferAmount := big.NewInt(testvalues.TransferAmount) + userAddressA := crypto.PubkeyToAddress(s.chainA.user.PublicKey) + userAddressB := crypto.PubkeyToAddress(s.chainB.user.PublicKey) + ics20AddressA := ethcommon.HexToAddress(s.chainA.contractAddresses.Ics20Transfer) + ics26AddressA := ethcommon.HexToAddress(s.chainA.contractAddresses.Ics26Router) + ics26AddressB := ethcommon.HexToAddress(s.chainB.contractAddresses.Ics26Router) + erc20AddressA := ethcommon.HexToAddress(s.chainA.contractAddresses.Erc20) + + var ( + sendTxHash []byte + sendReceipt *ethtypes.Receipt + sendPacket ics26router.IICS26RouterMsgsPacket + recvReceipt *ethtypes.Receipt + ibcERC20OnB *ibcerc20.Contract + ackReceipt *ethtypes.Receipt + ) + + s.Require().True(s.Run("Fund user on Chain A", func() { + fundTx, err := s.chainA.erc20.Transfer(s.mustTransactOpts(&s.chainA, s.chainA.eth.Faucet), userAddressA, testvalues.StartingERC20Balance) + s.Require().NoError(err) + + fundReceipt, err := s.chainA.eth.GetTxReciept(ctx, fundTx.Hash()) + s.Require().NoError(err) + s.Require().Equal(ethtypes.ReceiptStatusSuccessful, fundReceipt.Status) + })) + + s.Require().True(s.Run("Approve ICS20 on Chain A", func() { + approveTx, err := s.chainA.erc20.Approve(s.mustTransactOpts(&s.chainA, s.chainA.user), ics20AddressA, transferAmount) + s.Require().NoError(err) + + approveReceipt, err := s.chainA.eth.GetTxReciept(ctx, approveTx.Hash()) + s.Require().NoError(err) + s.Require().Equal(ethtypes.ReceiptStatusSuccessful, approveReceipt.Status) + })) + + s.Require().True(s.Run("Send transfer from Chain A to Chain B", func() { + timeout := uint64(time.Now().Add(30 * time.Minute).Unix()) + sendTx, err := s.chainA.ics20.SendTransfer(s.mustTransactOpts(&s.chainA, s.chainA.user), ics20transfer.IICS20TransferMsgsSendTransferMsg{ + Denom: erc20AddressA, + Amount: transferAmount, + Receiver: strings.ToLower(userAddressB.Hex()), + TimeoutTimestamp: timeout, + SourceClient: besuToBesuClientOnA, + DestPort: transfertypes.PortID, + Memo: "", + }) + s.Require().NoError(err) + + sendReceipt, err = s.chainA.eth.GetTxReciept(ctx, sendTx.Hash()) + s.Require().NoError(err) + s.Require().Equal(ethtypes.ReceiptStatusSuccessful, sendReceipt.Status) + sendTxHash = sendTx.Hash().Bytes() + + sendEvent, err := e2esuite.GetEvmEvent(sendReceipt, s.chainA.ics26.ParseSendPacket) + s.Require().NoError(err) + sendPacket = sendEvent.Packet + })) + + s.Require().True(s.Run("Verify balances on Chain A after send", func() { + escrowAddress, err := s.chainA.ics20.GetEscrow(nil, besuToBesuClientOnA) + s.Require().NoError(err) + + escrowBalance, err := s.chainA.erc20.BalanceOf(nil, escrowAddress) + s.Require().NoError(err) + s.Require().Equal(0, transferAmount.Cmp(escrowBalance)) + + userBalanceA, err := s.chainA.erc20.BalanceOf(nil, userAddressA) + s.Require().NoError(err) + expectedBalanceA := new(big.Int).Sub(new(big.Int).Set(testvalues.StartingERC20Balance), transferAmount) + s.Require().Equal(0, expectedBalanceA.Cmp(userBalanceA)) + })) + + s.Require().True(s.Run("Relay packet to Chain B", func() { + var relayTx []byte + s.Require().True(s.Run("Retrieve relay tx", func() { + relayAB, err := s.relayerClient.RelayByTx(context.Background(), &proofapitypes.RelayByTxRequest{ + SrcChain: s.chainA.eth.ChainID.String(), + DstChain: s.chainB.eth.ChainID.String(), + SourceTxIds: [][]byte{sendTxHash}, + SrcClientId: besuToBesuClientOnA, + DstClientId: besuToBesuClientOnB, + }) + s.Require().NoError(err) + s.Require().NotEmpty(relayAB.Tx) + s.Require().Equal(strings.ToLower(s.chainB.contractAddresses.Ics26Router), strings.ToLower(relayAB.Address)) + relayTx = relayAB.Tx + })) + + s.Require().True(s.Run("Broadcast relay tx on Chain B", func() { + var err error + recvReceipt, err = s.chainB.eth.BroadcastTx(ctx, s.chainB.relayerSubmitter, 15_000_000, &ics26AddressB, relayTx) + s.Require().NoError(err) + s.Require().Equal(ethtypes.ReceiptStatusSuccessful, recvReceipt.Status) + + writeAckEvent, err := e2esuite.GetEvmEvent(recvReceipt, s.chainB.ics26.ParseWriteAcknowledgement) + s.Require().NoError(err) + + ibcDenomOnB := fmt.Sprintf( + "%s/%s/%s", + writeAckEvent.Packet.Payloads[0].DestPort, + writeAckEvent.Packet.DestClient, + strings.ToLower(erc20AddressA.Hex()), + ) + ibcERC20AddressOnB, err := s.chainB.ics20.IbcERC20Contract(nil, ibcDenomOnB) + s.Require().NoError(err) + ibcERC20OnB, err = ibcerc20.NewContract(ibcERC20AddressOnB, s.chainB.eth.RPCClient) + s.Require().NoError(err) + })) + })) + + s.Require().True(s.Run("Verify balances on Chain B after receive", func() { + userBalanceB, err := ibcERC20OnB.BalanceOf(nil, userAddressB) + s.Require().NoError(err) + s.Require().Equal(0, transferAmount.Cmp(userBalanceB)) + })) + + s.Require().True(s.Run("Relay acknowledgement to Chain A", func() { + var relayTx []byte + s.Require().True(s.Run("Retrieve acknowledgement relay tx", func() { + ackRelay, err := s.relayerClient.RelayByTx(context.Background(), &proofapitypes.RelayByTxRequest{ + SrcChain: s.chainB.eth.ChainID.String(), + DstChain: s.chainA.eth.ChainID.String(), + SourceTxIds: [][]byte{recvReceipt.TxHash.Bytes()}, + SrcClientId: besuToBesuClientOnB, + DstClientId: besuToBesuClientOnA, + }) + s.Require().NoError(err) + s.Require().NotEmpty(ackRelay.Tx) + s.Require().Equal(strings.ToLower(s.chainA.contractAddresses.Ics26Router), strings.ToLower(ackRelay.Address)) + relayTx = ackRelay.Tx + })) + + s.Require().True(s.Run("Broadcast acknowledgement relay tx on Chain A", func() { + var err error + ackReceipt, err = s.chainA.eth.BroadcastTx(ctx, s.chainA.relayerSubmitter, 15_000_000, &ics26AddressA, relayTx) + s.Require().NoError(err) + s.Require().Equal(ethtypes.ReceiptStatusSuccessful, ackReceipt.Status) + + _, err = e2esuite.GetEvmEvent(ackReceipt, s.chainA.ics26.ParseAckPacket) + s.Require().NoError(err) + })) + })) + + if s.besuFixtureGenerator.Enabled { + s.Require().True(s.Run("Generate QBFT fixture", func() { + sendHeight := sendReceipt.BlockNumber.Uint64() + s.Require().Greater(sendHeight, uint64(2)) + s.Require().Greater(ackReceipt.BlockNumber.Uint64(), sendHeight) + s.Require().NoError(s.besuFixtureGenerator.GenerateAndSaveQBFTFixture(ctx, e2etypes.GenerateQBFTFixtureParams{ + SourceChain: &s.chainA.eth, + RouterAddress: ics26AddressA, + Packet: sendPacket, + InitialTrustedHeight: sendHeight - 2, + AdjacentUpdateHeight: sendHeight - 1, + NonAdjacentUpdateHeight: sendHeight, + SyntheticSourceHeight: ackReceipt.BlockNumber.Uint64(), + TrustingPeriod: uint64(testvalues.DefaultTrustPeriod), + MaxClockDrift: uint64(testvalues.DefaultMaxClockDrift), + })) + })) + } +} + +func (s *BesuToBesuTestSuite) spinUpChain(ctx context.Context, params chainconfig.BesuQBFTParams) besuToBesuChainState { + network, err := chainconfig.SpinUpBesuQBFT(ctx, params) + s.Require().NoError(err) + + ethChain, err := ethereum.NewEthereum(ctx, network.RPC, nil, network.Faucet) + s.Require().NoError(err) + + return besuToBesuChainState{ + network: network, + eth: ethChain, + } +} + +func (s *BesuToBesuTestSuite) createUsers(chain *besuToBesuChainState) { + var err error + chain.deployer, err = chain.eth.CreateAndFundUser() + s.Require().NoError(err) + chain.user, err = chain.eth.CreateAndFundUser() + s.Require().NoError(err) + chain.relayerSubmitter, err = chain.eth.CreateAndFundUser() + s.Require().NoError(err) +} + +func (s *BesuToBesuTestSuite) deployContracts(chain *besuToBesuChainState) { + os.Setenv(testvalues.EnvKeyEthRPC, chain.eth.RPC) + + stdout, err := chain.eth.ForgeScript(chain.deployer, testvalues.E2EDeployScriptPath, "--slow") + s.Require().NoError(err) + + chain.contractAddresses, err = ethereum.GetEthContractsFromDeployOutput(string(stdout)) + s.Require().NoError(err) + + chain.ics26, err = ics26router.NewContract(ethcommon.HexToAddress(chain.contractAddresses.Ics26Router), chain.eth.RPCClient) + s.Require().NoError(err) + chain.ics20, err = ics20transfer.NewContract(ethcommon.HexToAddress(chain.contractAddresses.Ics20Transfer), chain.eth.RPCClient) + s.Require().NoError(err) + chain.erc20, err = erc20.NewContract(ethcommon.HexToAddress(chain.contractAddresses.Erc20), chain.eth.RPCClient) + s.Require().NoError(err) +} + +func (s *BesuToBesuTestSuite) startRelayer() { + config := proofapi.NewConfigBuilder(). + BesuToEth(proofapi.BesuToEthParams{ + SrcChainID: s.chainA.eth.ChainID.String(), + DstChainID: s.chainB.eth.ChainID.String(), + SrcRPC: s.chainA.eth.RPC, + DstRPC: s.chainB.eth.RPC, + SrcICS26: s.chainA.contractAddresses.Ics26Router, + DstICS26: s.chainB.contractAddresses.Ics26Router, + ConsensusType: besuToBesuConsensusTypeQBFT, + }). + BesuToEth(proofapi.BesuToEthParams{ + SrcChainID: s.chainB.eth.ChainID.String(), + DstChainID: s.chainA.eth.ChainID.String(), + SrcRPC: s.chainB.eth.RPC, + DstRPC: s.chainA.eth.RPC, + SrcICS26: s.chainB.contractAddresses.Ics26Router, + DstICS26: s.chainA.contractAddresses.Ics26Router, + ConsensusType: besuToBesuConsensusTypeQBFT, + }). + Build() + + s.relayerConfigPath = filepath.Join(os.TempDir(), fmt.Sprintf("besu-to-besu-relayer-%d.json", time.Now().UnixNano())) + s.Require().NoError(config.GenerateConfigFile(s.relayerConfigPath)) + + var err error + s.relayerProcess, err = proofapi.StartProofAPI(s.relayerConfigPath) + s.Require().NoError(err) +} + +func (s *BesuToBesuTestSuite) connectRelayer() { + var err error + s.relayerClient, err = proofapi.GetGRPCClient(proofapi.DefaultProofAPIGRPCAddress()) + s.Require().NoError(err) + + infoAB := s.waitForRelayerInfo(s.chainA.eth.ChainID.String(), s.chainB.eth.ChainID.String()) + s.Require().Equal(s.chainA.eth.ChainID.String(), infoAB.SourceChain.ChainId) + s.Require().Equal(s.chainB.eth.ChainID.String(), infoAB.TargetChain.ChainId) + + infoBA := s.waitForRelayerInfo(s.chainB.eth.ChainID.String(), s.chainA.eth.ChainID.String()) + s.Require().Equal(s.chainB.eth.ChainID.String(), infoBA.SourceChain.ChainId) + s.Require().Equal(s.chainA.eth.ChainID.String(), infoBA.TargetChain.ChainId) +} + +func (s *BesuToBesuTestSuite) waitForRelayerInfo(srcChainID, dstChainID string) *proofapitypes.InfoResponse { + var ( + info *proofapitypes.InfoResponse + err error + ) + + for range 20 { + info, err = s.relayerClient.Info(context.Background(), &proofapitypes.InfoRequest{ + SrcChain: srcChainID, + DstChain: dstChainID, + }) + if err == nil { + return info + } + time.Sleep(time.Second) + } + + s.Require().NoError(err) + return info +} + +func (s *BesuToBesuTestSuite) createAndRegisterBesuClient( + srcChain *besuToBesuChainState, + dstChain *besuToBesuChainState, + dstClientID string, + counterpartyClientID string, +) { + resp, err := s.relayerClient.CreateClient(context.Background(), &proofapitypes.CreateClientRequest{ + SrcChain: srcChain.eth.ChainID.String(), + DstChain: dstChain.eth.ChainID.String(), + Parameters: map[string]string{ + testvalues.ParameterKey_TrustingPeriod: strconv.Itoa(testvalues.DefaultTrustPeriod), + testvalues.ParameterKey_MaxClockDrift: strconv.Itoa(testvalues.DefaultMaxClockDrift), + testvalues.ParameterKey_RoleManager: dstChain.contractAddresses.Ics26Router, + }, + }) + s.Require().NoError(err) + s.Require().NotEmpty(resp.Tx) + + createClientReceipt, err := dstChain.eth.BroadcastTx(context.Background(), dstChain.relayerSubmitter, 15_000_000, nil, resp.Tx) + s.Require().NoError(err) + s.Require().Equal(ethtypes.ReceiptStatusSuccessful, createClientReceipt.Status) + s.Require().NotEqual(ethcommon.Address{}, createClientReceipt.ContractAddress) + + counterpartyInfo := ics26router.IICS02ClientMsgsCounterpartyInfo{ + ClientId: counterpartyClientID, + MerklePrefix: [][]byte{[]byte("")}, + } + addClientTx, err := dstChain.ics26.AddClient( + s.mustTransactOpts(dstChain, dstChain.deployer), + dstClientID, + counterpartyInfo, + createClientReceipt.ContractAddress, + ) + s.Require().NoError(err) + + addClientReceipt, err := dstChain.eth.GetTxReciept(context.Background(), addClientTx.Hash()) + s.Require().NoError(err) + s.Require().Equal(ethtypes.ReceiptStatusSuccessful, addClientReceipt.Status) + + addClientEvent, err := e2esuite.GetEvmEvent(addClientReceipt, dstChain.ics26.ParseICS02ClientAdded) + s.Require().NoError(err) + s.Require().Equal(dstClientID, addClientEvent.ClientId) + s.Require().Equal(createClientReceipt.ContractAddress, addClientEvent.Client) + + registeredClient, err := dstChain.ics26.GetClient(nil, dstClientID) + s.Require().NoError(err) + s.Require().Equal(createClientReceipt.ContractAddress, registeredClient) + + dstChain.clientAddress = createClientReceipt.ContractAddress +} + +func (s *BesuToBesuTestSuite) mustTransactOpts(chain *besuToBesuChainState, key *ecdsa.PrivateKey) *bind.TransactOpts { + txOpts, err := chain.eth.GetTransactOpts(key) + s.Require().NoError(err) + return txOpts +} diff --git a/e2e/interchaintestv8/chainconfig/besu_qbft.go b/e2e/interchaintestv8/chainconfig/besu_qbft.go new file mode 100644 index 000000000..a0990c5ad --- /dev/null +++ b/e2e/interchaintestv8/chainconfig/besu_qbft.go @@ -0,0 +1,393 @@ +// SPDX-License-Identifier: Apache-2.0 + +package chainconfig + +import ( + "context" + "crypto/ecdsa" + "embed" + "encoding/json" + "fmt" + "io/fs" + "math/big" + "os" + "os/exec" + "path/filepath" + "strings" + "time" + + dockernetwork "github.com/docker/docker/api/types/network" + dockerclient "github.com/moby/moby/client" + + "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/cosmos/interchaintest/v11/testutil" + + "github.com/srdtrk/solidity-ibc-eureka/e2e/v8/testvalues" +) + +const ( + besuQBFTComposeFile = "docker-compose.yml" + besuQBFTProjectName = "besu-qbft" + + defaultBesuQBFTChainID uint64 = 1337 + defaultBesuQBFTSubnet = "10.42.0.0/16" + defaultBesuQBFTGateway = "10.42.0.1" + + besuQBFTTxProbeReceiptTimeout = 30 * time.Second +) + +var defaultBesuQBFTValidatorIPs = [4]string{"10.42.0.2", "10.42.0.3", "10.42.0.4", "10.42.0.5"} + +//go:embed testdata/besu/qbft +var besuQBFTAssets embed.FS + +var besuQBFTServices = []string{"validator1", "validator2", "validator3", "validator4"} + +type BesuQBFTParams struct { + ChainID uint64 + Subnet string + Gateway string + ValidatorIPs [4]string + DockerRPCAlias string + InterchainNetworkID string +} + +// DefaultBesuQBFTParams returns the topology from the embedded Besu fixture. +func DefaultBesuQBFTParams() BesuQBFTParams { + return BesuQBFTParams{ + ChainID: defaultBesuQBFTChainID, + Subnet: defaultBesuQBFTSubnet, + Gateway: defaultBesuQBFTGateway, + ValidatorIPs: defaultBesuQBFTValidatorIPs, + } +} + +type BesuQBFTChain struct { + RPC string + DockerRPC string + Faucet *ecdsa.PrivateKey + + projectName string + projectDir string +} + +func (c BesuQBFTChain) WaitForTransactionHandling(ctx context.Context) error { + return waitForBesuQBFTTransactionHandling(ctx, c.RPC, c.Faucet) +} + +func SpinUpBesuQBFT(ctx context.Context, params BesuQBFTParams) (chain BesuQBFTChain, err error) { + faucet, err := crypto.HexToECDSA(testvalues.E2EDeployerPrivateKeyHex) + if err != nil { + return BesuQBFTChain{}, fmt.Errorf("parse besu qbft faucet key: %w", err) + } + + projectDir, err := os.MkdirTemp("", besuQBFTProjectName+"-*") + if err != nil { + return BesuQBFTChain{}, fmt.Errorf("create besu qbft temp dir: %w", err) + } + + chain = BesuQBFTChain{ + Faucet: faucet, + projectDir: projectDir, + } + cleanupChain := BesuQBFTChain{projectDir: projectDir} + defer func() { + if err != nil { + cleanupCtx := context.Background() + if cleanupChain.projectName != "" { + if logErr := cleanupChain.DumpLogs(cleanupCtx); logErr != nil { + fmt.Printf("failed to dump besu qbft logs after startup error: %v\n", logErr) + } + } + cleanupChain.Destroy(cleanupCtx) + } + }() + + if err := materializeBesuQBFTAssets(projectDir); err != nil { + return BesuQBFTChain{}, fmt.Errorf("materialize besu qbft assets: %w", err) + } + + if err := patchBesuQBFTGenesis(filepath.Join(projectDir, "genesis.json"), params.ChainID); err != nil { + return BesuQBFTChain{}, fmt.Errorf("patch besu qbft genesis: %w", err) + } + + if err := patchBesuQBFTCompose(filepath.Join(projectDir, besuQBFTComposeFile), params); err != nil { + return BesuQBFTChain{}, fmt.Errorf("patch besu qbft compose file: %w", err) + } + + chain.projectName = filepath.Base(projectDir) + cleanupChain.projectName = chain.projectName + if _, err := chain.runCompose(ctx, "up", "--detach"); err != nil { + return BesuQBFTChain{}, fmt.Errorf("start besu qbft compose stack: %w", err) + } + + validator1Output, err := chain.runCompose(ctx, "ps", "-q", "validator1") + if err != nil { + return BesuQBFTChain{}, fmt.Errorf("get validator1 container: %w", err) + } + validator1ID := strings.TrimSpace(string(validator1Output)) + if validator1ID == "" { + return BesuQBFTChain{}, fmt.Errorf("get validator1 container: docker compose returned no container ID") + } + + dockerClient, err := dockerclient.NewClientWithOpts(dockerclient.FromEnv, dockerclient.WithAPIVersionNegotiation()) + if err != nil { + return BesuQBFTChain{}, fmt.Errorf("create docker client: %w", err) + } + defer dockerClient.Close() + + validator1, err := dockerClient.ContainerInspect(ctx, validator1ID) + if err != nil { + return BesuQBFTChain{}, fmt.Errorf("inspect validator1 container: %w", err) + } + if validator1.NetworkSettings == nil { + return BesuQBFTChain{}, fmt.Errorf("resolve validator1 rpc port: container has no network settings") + } + bindings := validator1.NetworkSettings.Ports["8545/tcp"] + if len(bindings) == 0 || bindings[0].HostPort == "" { + return BesuQBFTChain{}, fmt.Errorf("resolve validator1 rpc port: no 8545/tcp binding") + } + + chain.RPC = fmt.Sprintf("http://127.0.0.1:%s", bindings[0].HostPort) + if params.DockerRPCAlias != "" { + chain.DockerRPC = fmt.Sprintf("http://%s:8545", params.DockerRPCAlias) + } + + if params.InterchainNetworkID != "" { + settings := &dockernetwork.EndpointSettings{} + if params.DockerRPCAlias != "" { + settings.Aliases = []string{params.DockerRPCAlias} + } + if err := dockerClient.NetworkConnect(ctx, params.InterchainNetworkID, validator1ID, settings); err != nil { + return BesuQBFTChain{}, fmt.Errorf("connect besu qbft rpc container to interchain network: %w", err) + } + } + + if err := waitForBesuQBFTReady(ctx, chain.RPC); err != nil { + return BesuQBFTChain{}, fmt.Errorf("wait for besu qbft readiness: %w", err) + } + + if err := waitForBesuQBFTTransactionHandling(ctx, chain.RPC, faucet); err != nil { + return BesuQBFTChain{}, fmt.Errorf("wait for besu qbft transaction handling: %w", err) + } + + return chain, nil +} + +func (c BesuQBFTChain) Destroy(ctx context.Context) { + if c.projectName != "" && c.projectDir != "" { + if _, err := c.runCompose(ctx, "down", "--volumes", "--remove-orphans"); err != nil { + fmt.Printf("failed to tear down besu qbft stack: %v\n", err) + } + } + + if c.projectDir != "" { + if err := os.RemoveAll(c.projectDir); err != nil { + fmt.Printf("failed to remove besu qbft temp dir %s: %v\n", c.projectDir, err) + } + } +} + +func (c BesuQBFTChain) DumpLogs(ctx context.Context) error { + if c.projectName == "" || c.projectDir == "" { + return nil + } + + args := append([]string{"logs", "--no-color"}, besuQBFTServices...) + logs, err := c.runCompose(ctx, args...) + if len(logs) > 0 { + fmt.Print(string(logs)) + } + return err +} + +func (c BesuQBFTChain) runCompose(ctx context.Context, args ...string) ([]byte, error) { + composeArgs := []string{ + "compose", + "--project-name", c.projectName, + "--file", filepath.Join(c.projectDir, besuQBFTComposeFile), + } + composeArgs = append(composeArgs, args...) + + output, err := exec.CommandContext(ctx, "docker", composeArgs...).CombinedOutput() + if err != nil { + return output, fmt.Errorf("docker compose %s: %w: %s", strings.Join(args, " "), err, strings.TrimSpace(string(output))) + } + return output, nil +} + +func materializeBesuQBFTAssets(dst string) error { + sub, err := fs.Sub(besuQBFTAssets, "testdata/besu/qbft") + if err != nil { + return err + } + + return os.CopyFS(dst, sub) +} + +func patchBesuQBFTGenesis(path string, chainID uint64) error { + contents, err := os.ReadFile(path) + if err != nil { + return err + } + + var genesis map[string]any + if err := json.Unmarshal(contents, &genesis); err != nil { + return err + } + + config, ok := genesis["config"].(map[string]any) + if !ok { + return fmt.Errorf("genesis config missing or invalid") + } + config["chainId"] = chainID + + updated, err := json.MarshalIndent(genesis, "", " ") + if err != nil { + return err + } + updated = append(updated, '\n') + + // Besu reads the generated genesis file as an unprivileged container user. + return os.WriteFile(path, updated, 0o644) //nolint:gosec +} + +func patchBesuQBFTCompose(path string, params BesuQBFTParams) error { + contents, err := os.ReadFile(path) + if err != nil { + return err + } + + replacer := strings.NewReplacer( + defaultBesuQBFTSubnet, params.Subnet, + defaultBesuQBFTGateway, params.Gateway, + defaultBesuQBFTValidatorIPs[0], params.ValidatorIPs[0], + defaultBesuQBFTValidatorIPs[1], params.ValidatorIPs[1], + defaultBesuQBFTValidatorIPs[2], params.ValidatorIPs[2], + defaultBesuQBFTValidatorIPs[3], params.ValidatorIPs[3], + ) + + // Docker Compose reads this generated configuration outside the Go process. + return os.WriteFile(path, []byte(replacer.Replace(string(contents))), 0o644) //nolint:gosec +} + +func waitForBesuQBFTReady(ctx context.Context, rpcURL string) error { + client, err := ethclient.DialContext(ctx, rpcURL) + if err != nil { + return fmt.Errorf("dial readiness rpc: %w", err) + } + defer client.Close() + + var lastErr error + err = testutil.WaitForCondition(3*time.Minute, 2*time.Second, func() (bool, error) { + peerCount, err := client.PeerCount(ctx) + if err != nil { + lastErr = err + return false, nil + } + if peerCount < uint64(len(besuQBFTServices)-1) { + lastErr = fmt.Errorf("peer count %d, want at least %d", peerCount, len(besuQBFTServices)-1) + return false, nil + } + + blockNumber, err := client.BlockNumber(ctx) + if err != nil { + lastErr = err + return false, nil + } + if blockNumber == 0 { + lastErr = fmt.Errorf("block number is still zero") + return false, nil + } + + var validators []common.Address + if err := client.Client().CallContext(ctx, &validators, "qbft_getValidatorsByBlockNumber", "latest"); err != nil { + lastErr = err + return false, nil + } + + if len(validators) != len(besuQBFTServices) { + lastErr = fmt.Errorf("validator count %d, want exactly %d", len(validators), len(besuQBFTServices)) + return false, nil + } + + return true, nil + }) + if err != nil && lastErr != nil { + return fmt.Errorf("%w (last readiness observation: %v)", err, lastErr) + } + return err +} + +func waitForBesuQBFTTransactionHandling(ctx context.Context, rpcURL string, key *ecdsa.PrivateKey) error { + client, err := ethclient.DialContext(ctx, rpcURL) + if err != nil { + return fmt.Errorf("dial transaction probe rpc: %w", err) + } + defer client.Close() + + var lastErr error + err = testutil.WaitForCondition(2*time.Minute, 2*time.Second, func() (bool, error) { + txHash, err := sendBesuQBFTProbeTx(ctx, client, key) + if err != nil { + lastErr = err + return false, nil + } + + receiptCtx, cancel := context.WithTimeout(ctx, besuQBFTTxProbeReceiptTimeout) + receipt, err := bind.WaitMinedHash(receiptCtx, client, txHash) + cancel() + if err != nil { + lastErr = err + return false, nil + } + if receipt.Status != ethtypes.ReceiptStatusSuccessful { + return false, fmt.Errorf("besu qbft transaction probe failed on-chain with status %d", receipt.Status) + } + + return true, nil + }) + if err != nil && lastErr != nil { + return fmt.Errorf("%w (last transaction probe error: %v)", err, lastErr) + } + return err +} + +func sendBesuQBFTProbeTx(ctx context.Context, client *ethclient.Client, key *ecdsa.PrivateKey) (common.Hash, error) { + from := crypto.PubkeyToAddress(key.PublicKey) + + chainID, err := client.ChainID(ctx) + if err != nil { + return common.Hash{}, err + } + + nonce, err := client.PendingNonceAt(ctx, from) + if err != nil { + return common.Hash{}, err + } + + tx := ethtypes.NewTx(ðtypes.DynamicFeeTx{ + ChainID: chainID, + Nonce: nonce, + To: &from, + Value: big.NewInt(0), + Gas: 21_000, + GasFeeCap: big.NewInt(1), + GasTipCap: big.NewInt(1), + }) + + signedTx, err := ethtypes.SignTx(tx, ethtypes.LatestSignerForChainID(chainID), key) + if err != nil { + return common.Hash{}, err + } + if err := client.SendTransaction(ctx, signedTx); err != nil { + return common.Hash{}, err + } + + return signedTx.Hash(), nil +} diff --git a/e2e/interchaintestv8/chainconfig/testdata/besu/qbft/config.toml b/e2e/interchaintestv8/chainconfig/testdata/besu/qbft/config.toml new file mode 100644 index 000000000..3c5b75f9a --- /dev/null +++ b/e2e/interchaintestv8/chainconfig/testdata/besu/qbft/config.toml @@ -0,0 +1,13 @@ +genesis-file="/opt/besu/genesis.json" +data-path="/opt/besu/data" +node-private-key-file="/opt/besu/key" +data-storage-format="BONSAI" +bonsai-limit-trie-logs-enabled=false +rpc-http-enabled=true +rpc-http-host="0.0.0.0" +rpc-http-api=["ETH","NET","QBFT","WEB3","DEBUG"] +host-allowlist=["*"] +rpc-http-cors-origins=["all"] +min-gas-price=0 +sync-min-peers=1 +tx-pool="legacy" diff --git a/e2e/interchaintestv8/chainconfig/testdata/besu/qbft/docker-compose.yml b/e2e/interchaintestv8/chainconfig/testdata/besu/qbft/docker-compose.yml new file mode 100644 index 000000000..69587a47d --- /dev/null +++ b/e2e/interchaintestv8/chainconfig/testdata/besu/qbft/docker-compose.yml @@ -0,0 +1,96 @@ +# SPDX-License-Identifier: Apache-2.0 + +services: + validator1: + image: hyperledger/besu:26.4.0 + environment: + BESU_OPTS: -Xms128m -Xmx512m -XX:ActiveProcessorCount=2 + command: + - --config-file=/opt/besu/config.toml + - --identity=validator1 + - --p2p-host=10.42.0.2 + - --p2p-port=30303 + volumes: + - ./config.toml:/opt/besu/config.toml:ro + - ./genesis.json:/opt/besu/genesis.json:ro + - ./keys/validator1/key:/opt/besu/key:ro + - validator1-data:/opt/besu/data + ports: + - "8545" + networks: + qbft_testnet: + ipv4_address: 10.42.0.2 + + validator2: + image: hyperledger/besu:26.4.0 + environment: + BESU_OPTS: -Xms128m -Xmx512m -XX:ActiveProcessorCount=2 + command: + - --config-file=/opt/besu/config.toml + - --identity=validator2 + - --bootnodes=enode://ad83ac93fcc30a30f3e1bb6467623e45719167be50d13dccd8361cbca478cb540069869d1bae16de0f8b17a28f26f1c6c4dc12e71f240b366c6ff6f02f3fb93e@10.42.0.2:30303 + - --p2p-host=10.42.0.3 + - --p2p-port=30304 + volumes: + - ./config.toml:/opt/besu/config.toml:ro + - ./genesis.json:/opt/besu/genesis.json:ro + - ./keys/validator2/key:/opt/besu/key:ro + - validator2-data:/opt/besu/data + networks: + qbft_testnet: + ipv4_address: 10.42.0.3 + + validator3: + image: hyperledger/besu:26.4.0 + environment: + BESU_OPTS: -Xms128m -Xmx512m -XX:ActiveProcessorCount=2 + command: + - --config-file=/opt/besu/config.toml + - --identity=validator3 + - --bootnodes=enode://ad83ac93fcc30a30f3e1bb6467623e45719167be50d13dccd8361cbca478cb540069869d1bae16de0f8b17a28f26f1c6c4dc12e71f240b366c6ff6f02f3fb93e@10.42.0.2:30303 + - --p2p-host=10.42.0.4 + - --p2p-port=30305 + volumes: + - ./config.toml:/opt/besu/config.toml:ro + - ./genesis.json:/opt/besu/genesis.json:ro + - ./keys/validator3/key:/opt/besu/key:ro + - validator3-data:/opt/besu/data + networks: + qbft_testnet: + ipv4_address: 10.42.0.4 + + validator4: + image: hyperledger/besu:26.4.0 + environment: + BESU_OPTS: -Xms128m -Xmx512m -XX:ActiveProcessorCount=2 + command: + - --config-file=/opt/besu/config.toml + - --identity=validator4 + - --bootnodes=enode://ad83ac93fcc30a30f3e1bb6467623e45719167be50d13dccd8361cbca478cb540069869d1bae16de0f8b17a28f26f1c6c4dc12e71f240b366c6ff6f02f3fb93e@10.42.0.2:30303 + - --p2p-host=10.42.0.5 + - --p2p-port=30306 + volumes: + - ./config.toml:/opt/besu/config.toml:ro + - ./genesis.json:/opt/besu/genesis.json:ro + - ./keys/validator4/key:/opt/besu/key:ro + - validator4-data:/opt/besu/data + networks: + qbft_testnet: + ipv4_address: 10.42.0.5 + +networks: + qbft_testnet: + driver: bridge + driver_opts: + com.docker.network.enable_ipv6: "false" + ipam: + driver: default + config: + - subnet: 10.42.0.0/16 + gateway: 10.42.0.1 + +volumes: + validator1-data: + validator2-data: + validator3-data: + validator4-data: diff --git a/e2e/interchaintestv8/chainconfig/testdata/besu/qbft/genesis.json b/e2e/interchaintestv8/chainconfig/testdata/besu/qbft/genesis.json new file mode 100644 index 000000000..85f58aa50 --- /dev/null +++ b/e2e/interchaintestv8/chainconfig/testdata/besu/qbft/genesis.json @@ -0,0 +1,24 @@ +{ + "config": { + "chainId": 1337, + "cancunTime": 0, + "zeroBaseFee": true, + "qbft": { + "blockperiodseconds": 2, + "epochlength": 30000, + "requesttimeoutseconds": 4 + } + }, + "nonce": "0x0", + "timestamp": "0x58ee40ba", + "gasLimit": "0x2faf080", + "difficulty": "0x1", + "mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365", + "coinbase": "0x0000000000000000000000000000000000000000", + "alloc": { + "f39fd6e51aad88f6f4ce6ab8827279cfffb92266": { + "balance": "1000000000000000000000000" + } + }, + "extraData": "0xf87aa00000000000000000000000000000000000000000000000000000000000000000f85494065f139d8a49e9926232cc4435159024cb5064fc940eb968de631abc65322ecdca5dfdf9c6296e52f494543d3796700ee35803a1c43562a69fec08e1e4239420c5edbcf6263cd9e30df395a2b914f6e939b9bac080c0" +} diff --git a/e2e/interchaintestv8/chainconfig/testdata/besu/qbft/keys/validator1/key b/e2e/interchaintestv8/chainconfig/testdata/besu/qbft/keys/validator1/key new file mode 100644 index 000000000..0a70c443d --- /dev/null +++ b/e2e/interchaintestv8/chainconfig/testdata/besu/qbft/keys/validator1/key @@ -0,0 +1 @@ +0x18fddb41c4f6316532162f1c54a0cf4c62562b499c392720f04e7d33e32e88fa diff --git a/e2e/interchaintestv8/chainconfig/testdata/besu/qbft/keys/validator2/key b/e2e/interchaintestv8/chainconfig/testdata/besu/qbft/keys/validator2/key new file mode 100644 index 000000000..43586a8fe --- /dev/null +++ b/e2e/interchaintestv8/chainconfig/testdata/besu/qbft/keys/validator2/key @@ -0,0 +1 @@ +0x9a4cc956527624fba01e932a28f982233b8169d840b72a9089cd0d3da127ccb6 diff --git a/e2e/interchaintestv8/chainconfig/testdata/besu/qbft/keys/validator3/key b/e2e/interchaintestv8/chainconfig/testdata/besu/qbft/keys/validator3/key new file mode 100644 index 000000000..b2049aeca --- /dev/null +++ b/e2e/interchaintestv8/chainconfig/testdata/besu/qbft/keys/validator3/key @@ -0,0 +1 @@ +0x2fd21d48dcb473933de188ff882fed9d3bcbc4d43af77172f1b8035f1574a19b diff --git a/e2e/interchaintestv8/chainconfig/testdata/besu/qbft/keys/validator4/key b/e2e/interchaintestv8/chainconfig/testdata/besu/qbft/keys/validator4/key new file mode 100644 index 000000000..a2903bdff --- /dev/null +++ b/e2e/interchaintestv8/chainconfig/testdata/besu/qbft/keys/validator4/key @@ -0,0 +1 @@ +0xa9b2b5406572152ceb0a5480a65f63fc562e6970402dd58ede1bec32837ae25a diff --git a/e2e/interchaintestv8/e2esuite/config.go b/e2e/interchaintestv8/e2esuite/config.go index a0693a5ad..0424d01bd 100644 --- a/e2e/interchaintestv8/e2esuite/config.go +++ b/e2e/interchaintestv8/e2esuite/config.go @@ -34,6 +34,10 @@ func (c *ethereumConfig) isAnvilBased() bool { return c.testnetType == testvalues.EthTestnetTypeAnvil } +func (c *ethereumConfig) isBesuQBFT() bool { + return c.testnetType == testvalues.EthTestnetTypeBesuQBFT +} + func (c *ethereumConfig) needsPoS() bool { return c.testnetType == testvalues.EthTestnetTypePoS } @@ -61,22 +65,29 @@ func (c *setupConfig) validate() error { ethTestnetType := c.ethereum.testnetType ethLcOnCosmos := c.cosmos.lightClientType - // Skip validation if no ethereum chain - if ethTestnetType == "" || ethTestnetType == testvalues.EthTestnetType_None { + switch ethTestnetType { + case "", testvalues.EthTestnetType_None: return nil + case testvalues.EthTestnetTypeAnvil: + if c.ethereum.anvilCount > 1 { + return nil + } + if ethLcOnCosmos == testvalues.EthLCOnCosmosTypeDummyWasm || ethLcOnCosmos == testvalues.EthLCOnCosmosTypeAttestorNative { + return nil + } + case testvalues.EthTestnetTypePoS: + if ethLcOnCosmos == testvalues.EthLCOnCosmosTypeFullWasm || ethLcOnCosmos == testvalues.EthLCOnCosmosTypeAttestorNative { + return nil + } + case testvalues.EthTestnetTypeBesuQBFT: + if ethLcOnCosmos == testvalues.EthLCOnCosmosTypeAttestorNative { + return nil + } + default: + return fmt.Errorf("invalid config: unsupported ETH_TESTNET_TYPE=%s", ethTestnetType) } - // Anvil cannot use full light client (no beacon chain to verify) - if c.ethereum.isAnvilBased() && ethLcOnCosmos == testvalues.EthLCOnCosmosTypeFullWasm { - return fmt.Errorf("invalid config: ETH_TESTNET_TYPE=%s cannot use ETH_LC_ON_COSMOS=%s (Anvil doesn't have beacon chain)", ethTestnetType, ethLcOnCosmos) - } - - // PoS testnets cannot use dummy light client (requires actual verification) - if !c.ethereum.isAnvilBased() && ethLcOnCosmos == testvalues.EthLCOnCosmosTypeDummyWasm { - return fmt.Errorf("invalid config: ETH_TESTNET_TYPE=%s cannot use ETH_LC_ON_COSMOS=%s (PoS requires actual verification)", ethTestnetType, ethLcOnCosmos) - } - - return nil + return fmt.Errorf("invalid config: ETH_TESTNET_TYPE=%s does not support ETH_LC_ON_COSMOS=%s", ethTestnetType, ethLcOnCosmos) } // Result types for parallel chain setup diff --git a/e2e/interchaintestv8/e2esuite/config_test.go b/e2e/interchaintestv8/e2esuite/config_test.go new file mode 100644 index 000000000..92b9e297f --- /dev/null +++ b/e2e/interchaintestv8/e2esuite/config_test.go @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: Apache-2.0 + +package e2esuite + +import ( + "testing" + + "github.com/srdtrk/solidity-ibc-eureka/e2e/v8/testvalues" +) + +func TestSetupConfigValidateEthereumCompatibility(t *testing.T) { + const unknown = "unknown" + + tests := []struct { + name string + testnetType string + clientType string + wantErr bool + }{ + {"anvil dummy", testvalues.EthTestnetTypeAnvil, testvalues.EthLCOnCosmosTypeDummyWasm, false}, + {"anvil attestor", testvalues.EthTestnetTypeAnvil, testvalues.EthLCOnCosmosTypeAttestorNative, false}, + {"pos full", testvalues.EthTestnetTypePoS, testvalues.EthLCOnCosmosTypeFullWasm, false}, + {"pos attestor", testvalues.EthTestnetTypePoS, testvalues.EthLCOnCosmosTypeAttestorNative, false}, + {"besu attestor", testvalues.EthTestnetTypeBesuQBFT, testvalues.EthLCOnCosmosTypeAttestorNative, false}, + {"anvil full", testvalues.EthTestnetTypeAnvil, testvalues.EthLCOnCosmosTypeFullWasm, true}, + {"pos dummy", testvalues.EthTestnetTypePoS, testvalues.EthLCOnCosmosTypeDummyWasm, true}, + {"besu dummy", testvalues.EthTestnetTypeBesuQBFT, testvalues.EthLCOnCosmosTypeDummyWasm, true}, + {"besu full", testvalues.EthTestnetTypeBesuQBFT, testvalues.EthLCOnCosmosTypeFullWasm, true}, + {"active empty client", testvalues.EthTestnetTypeAnvil, "", true}, + {"active unknown client", testvalues.EthTestnetTypePoS, unknown, true}, + {"unknown testnet", unknown, testvalues.EthLCOnCosmosTypeAttestorNative, true}, + {"disabled empty", "", unknown, false}, + {"disabled none", testvalues.EthTestnetType_None, unknown, false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cfg := setupConfig{ + ethereum: ethereumConfig{testnetType: tt.testnetType}, + cosmos: cosmosConfig{lightClientType: tt.clientType}, + } + if err := cfg.validate(); (err != nil) != tt.wantErr { + t.Fatalf("validate() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } + + for _, clientType := range []string{"", unknown} { + cfg := setupConfig{ + ethereum: ethereumConfig{testnetType: testvalues.EthTestnetTypeAnvil, anvilCount: 2}, + cosmos: cosmosConfig{lightClientType: clientType}, + } + if err := cfg.validate(); err != nil { + t.Errorf("multiple Anvil chains with ETH_LC_ON_COSMOS=%q: %v", clientType, err) + } + } +} diff --git a/e2e/interchaintestv8/e2esuite/setup_ethereum.go b/e2e/interchaintestv8/e2esuite/setup_ethereum.go index 50c002cfd..bd1eb8e7d 100644 --- a/e2e/interchaintestv8/e2esuite/setup_ethereum.go +++ b/e2e/interchaintestv8/e2esuite/setup_ethereum.go @@ -85,6 +85,37 @@ func (s *TestSuite) processEthereumPoSResult(ctx context.Context, chain *chainco s.Eth.Chains = append(s.Eth.Chains, ðChain) } +func (s *TestSuite) setupEthereumBesuQBFT(ctx context.Context, networkID string) (*chainconfig.BesuQBFTChain, error) { + params := chainconfig.DefaultBesuQBFTParams() + params.DockerRPCAlias = "besu-qbft-rpc" + params.InterchainNetworkID = networkID + + chain, err := chainconfig.SpinUpBesuQBFT(ctx, params) + if err != nil { + return nil, err + } + return &chain, nil +} + +func (s *TestSuite) processEthereumBesuQBFTResult(ctx context.Context, chain *chainconfig.BesuQBFTChain) { + if chain == nil { + return + } + + s.T().Cleanup(func() { + cleanupCtx := context.Background() + if s.T().Failed() { + _ = chain.DumpLogs(cleanupCtx) + } + chain.Destroy(cleanupCtx) + }) + + ethChain, err := ethereum.NewEthereum(ctx, chain.RPC, nil, chain.Faucet) + s.Require().NoError(err, "Failed to create Ethereum client") + ethChain.DockerRPC = chain.DockerRPC + s.Eth.Chains = append(s.Eth.Chains, ðChain) +} + // setupAnvilChains detects and sets up any Anvil chains in the slice. func (s *TestSuite) setupAnvilChains(ctx context.Context, chains []ibc.Chain) { faucet, err := crypto.HexToECDSA(testvalues.E2EDeployerPrivateKeyHex) diff --git a/e2e/interchaintestv8/e2esuite/suite.go b/e2e/interchaintestv8/e2esuite/suite.go index 51cd89564..d70bfaf97 100644 --- a/e2e/interchaintestv8/e2esuite/suite.go +++ b/e2e/interchaintestv8/e2esuite/suite.go @@ -16,6 +16,7 @@ import ( "github.com/cosmos/interchaintest/v11/ibc" "github.com/cosmos/interchaintest/v11/testreporter" + "github.com/srdtrk/solidity-ibc-eureka/e2e/v8/chainconfig" "github.com/srdtrk/solidity-ibc-eureka/e2e/v8/ethereum" "github.com/srdtrk/solidity-ibc-eureka/e2e/v8/solana" "github.com/srdtrk/solidity-ibc-eureka/e2e/v8/testvalues" @@ -128,17 +129,26 @@ func (s *TestSuite) setupChainsInParallel( ethPosCh <- ethPosSetupResult{} } + interchainRes := <-interchainCh + s.Require().NoError(interchainRes.err, "Interchain setup failed") + + var ethBesuQBFTChain *chainconfig.BesuQBFTChain + var ethBesuQBFTErr error + if cfg.ethereum.isBesuQBFT() { + ethBesuQBFTChain, ethBesuQBFTErr = s.setupEthereumBesuQBFT(ctx, interchainRes.network) + } + solanaRes := <-solanaCh s.Require().NoError(solanaRes.err, "Solana chain setup failed") s.processSolanaResult(solanaRes.chain) - interchainRes := <-interchainCh - s.Require().NoError(interchainRes.err, "Interchain setup failed") - ethPosRes := <-ethPosCh s.Require().NoError(ethPosRes.err, "Ethereum PoS chain setup failed") s.processEthereumPoSResult(ctx, ethPosRes.chain) + s.Require().NoError(ethBesuQBFTErr, "Ethereum Besu QBFT chain setup failed") + s.processEthereumBesuQBFTResult(ctx, ethBesuQBFTChain) + return interchainRes.chains, interchainRes.dockerClient, interchainRes.network, interchainRes.logger } diff --git a/e2e/interchaintestv8/ethereum/ethereum.go b/e2e/interchaintestv8/ethereum/ethereum.go index 54ff43b83..76e203fde 100644 --- a/e2e/interchaintestv8/ethereum/ethereum.go +++ b/e2e/interchaintestv8/ethereum/ethereum.go @@ -12,6 +12,7 @@ import ( "math/big" "os" "os/exec" + "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" ethcommon "github.com/ethereum/go-ethereum/common" @@ -24,6 +25,8 @@ import ( "github.com/srdtrk/solidity-ibc-eureka/e2e/v8/testvalues" ) +const forgeScriptTimeout = 5 * time.Minute + type Ethereum struct { ChainID *big.Int RPC string @@ -102,15 +105,20 @@ func (e *Ethereum) BroadcastTx(ctx context.Context, userKey *ecdsa.PrivateKey, g } func (e Ethereum) ForgeScript(deployer *ecdsa.PrivateKey, solidityContract string, args ...string) ([]byte, error) { + return e.forgeScript(forgeScriptTimeout, deployer, solidityContract, args...) +} + +func (e Ethereum) forgeScript(timeout time.Duration, deployer *ecdsa.PrivateKey, solidityContract string, args ...string) ([]byte, error) { cmdArgs := []string{ "script", "--rpc-url", e.RPC, "--private-key", hex.EncodeToString(crypto.FromECDSA(deployer)), "--broadcast", "--non-interactive", "-vvvv", solidityContract, } cmdArgs = append(cmdArgs, args...) - cmd := exec.Command( - "forge", cmdArgs..., - ) + ctx, cancel := context.WithTimeout(context.Background(), timeout) + defer cancel() + + cmd := exec.CommandContext(ctx, "forge", cmdArgs...) // Tests run from the repository root; forge must run from the Foundry project root // so that foundry.toml and script paths resolve. cmd.Dir = testvalues.SolidityProjectDir @@ -125,23 +133,20 @@ func (e Ethereum) ForgeScript(deployer *ecdsa.PrivateKey, solidityContract strin var stdoutBuf bytes.Buffer - // Create a MultiWriter to write to both os.Stdout and the buffer - multiWriter := io.MultiWriter(os.Stdout, &stdoutBuf) + // Preserve live output while retaining stdout for deploy-result parsing. + stdoutWriter := io.MultiWriter(os.Stdout, &stdoutBuf) - // Set the command's stdout to the MultiWriter - cmd.Stdout = multiWriter + cmd.Stdout = stdoutWriter cmd.Stderr = os.Stderr - // Run the command if err := cmd.Run(); err != nil { - fmt.Println("Error start command", cmd.Args, err) - return nil, err + if ctx.Err() == context.DeadlineExceeded { + return nil, fmt.Errorf("forge script %q timed out after %s: %w", solidityContract, timeout, ctx.Err()) + } + return nil, fmt.Errorf("forge script %q failed: %w", solidityContract, err) } - // Get the output as byte slices - stdoutBytes := stdoutBuf.Bytes() - - return stdoutBytes, nil + return stdoutBuf.Bytes(), nil } func (e Ethereum) CreateUser() (*ecdsa.PrivateKey, error) { diff --git a/e2e/interchaintestv8/ethereum/utils_test.go b/e2e/interchaintestv8/ethereum/utils_test.go index 7e8e1b046..a09d37bb8 100644 --- a/e2e/interchaintestv8/ethereum/utils_test.go +++ b/e2e/interchaintestv8/ethereum/utils_test.go @@ -11,126 +11,12 @@ import ( ) func TestGetEthAddressFromStdout(t *testing.T) { - exampleOutput := `Compiling 72 files with Solc 0.8.25 -Solc 0.8.25 finished in 2.43s -Compiler run successful! -Traces: - [13132696] E2ETestDeploy::run() - ├─ [0] VM::projectRoot() [staticcall] - │ └─ ← [Return] "/Users/gg/Code/solidity-ibc-eureka" - ├─ [0] VM::readFile("/Users/gg/Code/solidity-ibc-eureka/e2e/genesis.json") [staticcall] - │ └─ ← [Return] - ├─ [0] VM::parseJsonBytes("", ".trustedClientState") [staticcall] - │ └─ ← [Return] 0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000012754500000000000000000000000000000000000000000000000000000000001baf800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000673696d642d310000000000000000000000000000000000000000000000000000 - ├─ [0] VM::parseJsonBytes("", ".trustedConsensusState") [staticcall] - │ └─ ← [Return] 0x000000000000000000000000000000000000000000000000000000006708142974c0681a0dbf3e340cedb56abacacec3f01106cd13d1d240e6eb7fc60a34c31250d828ba2c80c290ee3edb5d12ec232dee758f20214af6fbd73a1f636f79d4d7 - ├─ [0] VM::parseJsonBytes32("", ".updateClientVkey") [staticcall] - │ └─ ← [Return] 0x00787fed71dce3ac5685c23cb727f0bbe41c9c40977506f33530f52eabab6c86 - ├─ [0] VM::parseJsonBytes32("", ".membershipVkey") [staticcall] - │ └─ ← [Return] 0x00a8f49c50bcef3ffaef3e8018be59281904d5951d6e20e0a824b9504da18c7f - ├─ [0] VM::parseJsonBytes32("", ".ucAndMembershipVkey") [staticcall] - │ └─ ← [Return] 0x0037bf750186b666717a245012144eb63d1c8675134c9a9c81133535c4f76656 - ├─ [0] VM::envUint("PRIVATE_KEY") [staticcall] - │ └─ ← [Return] - ├─ [0] VM::startBroadcast() - │ └─ ← [Return] - ├─ [2404781] → new SP1Verifier@0x867EBEE8fB04ef90a4161fe21b89420B0aeEF8f2 - │ └─ ← [Return] 12011 bytes of code - ├─ [2442427] → new SP1ICS07Tendermint@0x65cE09e5864dD1f45F4ae50396A307291AaD6631 - │ └─ ← [Return] 11624 bytes of code - ├─ [1171142] → new ICS02Client@0xEBC7C68E032d765e392CFf5B2a11E76C2C43BbbF - │ ├─ emit OwnershipTransferred(previousOwner: 0x0000000000000000000000000000000000000000, newOwner: 0x51A4283eBaeC10B9B764AE8B021BcAA30C0631Ff) - │ └─ ← [Return] 5730 bytes of code - ├─ [2953720] → new ICS26Router@0xfcf4c2FAc206cFABE9C2B68AefE5D0a9fA038501 - │ ├─ emit OwnershipTransferred(previousOwner: 0x0000000000000000000000000000000000000000, newOwner: 0x51A4283eBaeC10B9B764AE8B021BcAA30C0631Ff) - │ └─ ← [Return] 14411 bytes of code - ├─ [3299657] → new ICS20Transfer@0xD6D4C57D09bA13C9535Ee2d6BdB100231d793a22 - │ ├─ emit OwnershipTransferred(previousOwner: 0x0000000000000000000000000000000000000000, newOwner: ICS26Router: [0xfcf4c2FAc206cFABE9C2B68AefE5D0a9fA038501]) - │ └─ ← [Return] 16250 bytes of code - ├─ [531853] → new TestERC20@0x022b667cC0D57836CCb12669ce93Ae1e15d4f8BC - │ └─ ← [Return] 2431 bytes of code - ├─ [28083] ICS26Router::addIBCApp("transfer", ICS20Transfer: [0xD6D4C57D09bA13C9535Ee2d6BdB100231d793a22]) - │ ├─ emit IBCAppAdded(portId: "transfer", app: ICS20Transfer: [0xD6D4C57D09bA13C9535Ee2d6BdB100231d793a22]) - │ └─ ← [Stop] - ├─ [0] VM::stopBroadcast() - │ └─ ← [Return] - ├─ [0] VM::serializeString("", "ics07Tendermint", "0x65ce09e5864dd1f45f4ae50396a307291aad6631") - │ └─ ← [Return] "{\"ics07Tendermint\":\"0x65ce09e5864dd1f45f4ae50396a307291aad6631\"}" - ├─ [0] VM::serializeString("", "ics02Client", "0xebc7c68e032d765e392cff5b2a11e76c2c43bbbf") - │ └─ ← [Return] "{\"ics02Client\":\"0xebc7c68e032d765e392cff5b2a11e76c2c43bbbf\",\"ics07Tendermint\":\"0x65ce09e5864dd1f45f4ae50396a307291aad6631\"}" - ├─ [0] VM::serializeString("", "ics26Router", "0xfcf4c2fac206cfabe9c2b68aefe5d0a9fa038501") - │ └─ ← [Return] "{\"ics02Client\":\"0xebc7c68e032d765e392cff5b2a11e76c2c43bbbf\",\"ics07Tendermint\":\"0x65ce09e5864dd1f45f4ae50396a307291aad6631\",\"ics26Router\":\"0xfcf4c2fac206cfabe9c2b68aefe5d0a9fa038501\"}" - ├─ [0] VM::serializeString("", "ics20Transfer", "0xd6d4c57d09ba13c9535ee2d6bdb100231d793a22") - │ └─ ← [Return] "{\"ics02Client\":\"0xebc7c68e032d765e392cff5b2a11e76c2c43bbbf\",\"ics07Tendermint\":\"0x65ce09e5864dd1f45f4ae50396a307291aad6631\",\"ics20Transfer\":\"0xd6d4c57d09ba13c9535ee2d6bdb100231d793a22\",\"ics26Router\":\"0xfcf4c2fac206cfabe9c2b68aefe5d0a9fa038501\"}" - ├─ [0] VM::serializeString("", "erc20", "0x022b667cc0d57836ccb12669ce93ae1e15d4f8bc") - │ └─ ← [Return] "{\"erc20\":\"0x022b667cc0d57836ccb12669ce93ae1e15d4f8bc\",\"ics02Client\":\"0xebc7c68e032d765e392cff5b2a11e76c2c43bbbf\",\"ics07Tendermint\":\"0x65ce09e5864dd1f45f4ae50396a307291aad6631\",\"ics20Transfer\":\"0xd6d4c57d09ba13c9535ee2d6bdb100231d793a22\",\"ics26Router\":\"0xfcf4c2fac206cfabe9c2b68aefe5d0a9fa038501\"}" - └─ ← [Return] "{\"erc20\":\"0x022b667cc0d57836ccb12669ce93ae1e15d4f8bc\",\"ics02Client\":\"0xebc7c68e032d765e392cff5b2a11e76c2c43bbbf\",\"ics07Tendermint\":\"0x65ce09e5864dd1f45f4ae50396a307291aad6631\",\"ics20Transfer\":\"0xd6d4c57d09ba13c9535ee2d6bdb100231d793a22\",\"ics26Router\":\"0xfcf4c2fac206cfabe9c2b68aefe5d0a9fa038501\"}" + const output = `== Return == +0: string "{\"cosmosIftConstructor\":\"0x0000000000000000000000000000000000000000\",\"erc20\":\"0x851356ae760d987e095750cceb3bc6014560891c\",\"ics20Transfer\":\"0xb7f8bc63bbcad18155201308c8f3540b07f84f5e\",\"ics26Router\":\"0x2279b7a0a67db372996a5fab50d91eaa73d2ebe6\",\"ics27Gmp\":\"0x0dcd1bf9a1b36ce34237eeafef220932846bcd82\",\"ift\":\"0x0b306bf915c4d645ff596e518faf3f9669b97016\",\"solanaIftConstructor\":\"0x0000000000000000000000000000000000000000\",\"verifierGroth16\":\"0x9fe46736679d2d9a65f0992f2272de9f3c7fa6e0\",\"verifierMock\":\"0xcf7ed3acca5a467e9e704c703e8d87f634fb0fc9\",\"verifierPlonk\":\"0xe7f1725e7734ce288f8367e1bb143e90bb3f0512\"}"` - -Script ran successfully. - -== Return == -0: string "{\"erc20\":\"0x022b667cc0d57836ccb12669ce93ae1e15d4f8bc\",\"ics02Client\":\"0xebc7c68e032d765e392cff5b2a11e76c2c43bbbf\",\"ics07Tendermint\":\"0x65ce09e5864dd1f45f4ae50396a307291aad6631\",\"ics20Transfer\":\"0xd6d4c57d09ba13c9535ee2d6bdb100231d793a22\",\"ics26Router\":\"0xfcf4c2fac206cfabe9c2b68aefe5d0a9fa038501\"}" - -## Setting up 1 EVM. -========================== -Simulated On-chain Traces: - - [521379] → new ICS20Lib@0xDcC1FffeC88e1Fa830604047fad1Aa8D957A7DC7 - └─ ← [Return] 2604 bytes of code - - [2404781] → new SP1Verifier@0x867EBEE8fB04ef90a4161fe21b89420B0aeEF8f2 - └─ ← [Return] 12011 bytes of code - - [2442427] → new SP1ICS07Tendermint@0x65cE09e5864dD1f45F4ae50396A307291AaD6631 - └─ ← [Return] 11624 bytes of code - - [1171142] → new ICS02Client@0xEBC7C68E032d765e392CFf5B2a11E76C2C43BbbF - ├─ emit OwnershipTransferred(previousOwner: 0x0000000000000000000000000000000000000000, newOwner: 0x51A4283eBaeC10B9B764AE8B021BcAA30C0631Ff) - └─ ← [Return] 5730 bytes of code - - [2953720] → new ICS26Router@0xfcf4c2FAc206cFABE9C2B68AefE5D0a9fA038501 - ├─ emit OwnershipTransferred(previousOwner: 0x0000000000000000000000000000000000000000, newOwner: 0x51A4283eBaeC10B9B764AE8B021BcAA30C0631Ff) - └─ ← [Return] 14411 bytes of code - - [3299657] → new ICS20Transfer@0xD6D4C57D09bA13C9535Ee2d6BdB100231d793a22 - ├─ emit OwnershipTransferred(previousOwner: 0x0000000000000000000000000000000000000000, newOwner: ICS26Router: [0xfcf4c2FAc206cFABE9C2B68AefE5D0a9fA038501]) - └─ ← [Return] 16250 bytes of code - - [531853] → new TestERC20@0x022b667cC0D57836CCb12669ce93Ae1e15d4f8BC - └─ ← [Return] 2431 bytes of code - - [30083] ICS26Router::addIBCApp("transfer", ICS20Transfer: [0xD6D4C57D09bA13C9535Ee2d6BdB100231d793a22]) - ├─ emit IBCAppAdded(portId: "transfer", app: ICS20Transfer: [0xD6D4C57D09bA13C9535Ee2d6BdB100231d793a22]) - └─ ← [Stop] - - -========================== - -Chain 3151908 - -Estimated gas price: 0.460566435 gwei - -Estimated total gas used for script: 19196301 - -Estimated amount required: 0.008841171916756935 ETH - -========================== - - -========================== - -ONCHAIN EXECUTION COMPLETE & SUCCESSFUL. - -Transactions saved to: /Users/gg/Code/solidity-ibc-eureka/broadcast/E2ETestDeploy.s.sol/3151908/run-latest.json - -Sensitive values saved to: /Users/gg/Code/solidity-ibc-eureka/cache/E2ETestDeploy.s.sol/3151908/run-latest.json -` - - deployedContracts, err := ethereum.GetEthContractsFromDeployOutput(exampleOutput) + deployedContracts, err := ethereum.GetEthContractsFromDeployOutput(output) require.NoError(t, err) - - require.Equal(t, "0xfcf4c2fac206cfabe9c2b68aefe5d0a9fa038501", deployedContracts.Ics26Router) - require.Equal(t, "0xd6d4c57d09ba13c9535ee2d6bdb100231d793a22", deployedContracts.Ics20Transfer) - require.Equal(t, "0x022b667cc0d57836ccb12669ce93ae1e15d4f8bc", deployedContracts.Erc20) + require.Equal(t, "0x2279b7a0a67db372996a5fab50d91eaa73d2ebe6", deployedContracts.Ics26Router) + require.Equal(t, "0xb7f8bc63bbcad18155201308c8f3540b07f84f5e", deployedContracts.Ics20Transfer) + require.Equal(t, "0x851356ae760d987e095750cceb3bc6014560891c", deployedContracts.Erc20) } diff --git a/e2e/interchaintestv8/go.mod b/e2e/interchaintestv8/go.mod index bc4fb87f8..d5a7d2de9 100644 --- a/e2e/interchaintestv8/go.mod +++ b/e2e/interchaintestv8/go.mod @@ -39,6 +39,11 @@ require ( google.golang.org/protobuf v1.36.12 ) +require ( + github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect + github.com/urfave/cli/v2 v2.27.6 // indirect +) + require ( cel.dev/expr v0.25.2 // indirect cloud.google.com/go v0.123.0 // indirect @@ -244,7 +249,7 @@ require ( github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.24 // indirect - github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mholt/archives v0.1.5 // indirect github.com/miekg/dns v1.1.72 // indirect github.com/mikelolasagasti/xz v1.0.1 // indirect @@ -288,6 +293,7 @@ require ( github.com/petermattis/goid v0.0.0-20260330135022-df67b199bc81 // indirect github.com/pierrec/lz4/v4 v4.1.22 // indirect github.com/pion/datachannel v1.5.10 // indirect + github.com/pion/dtls/v2 v2.2.12 // indirect github.com/pion/dtls/v3 v3.1.2 // indirect github.com/pion/ice/v4 v4.0.10 // indirect github.com/pion/interceptor v0.1.40 // indirect @@ -299,7 +305,9 @@ require ( github.com/pion/sctp v1.8.39 // indirect github.com/pion/sdp/v3 v3.0.18 // indirect github.com/pion/srtp/v3 v3.0.6 // indirect + github.com/pion/stun/v2 v2.0.0 // indirect github.com/pion/stun/v3 v3.1.2 // indirect + github.com/pion/transport/v2 v2.2.10 // indirect github.com/pion/transport/v3 v3.0.7 // indirect github.com/pion/transport/v4 v4.0.1 // indirect github.com/pion/turn/v4 v4.0.2 // indirect diff --git a/e2e/interchaintestv8/go.sum b/e2e/interchaintestv8/go.sum index 12e1d81af..d58569efa 100644 --- a/e2e/interchaintestv8/go.sum +++ b/e2e/interchaintestv8/go.sum @@ -337,8 +337,9 @@ github.com/cosmos/ledger-cosmos-go v1.0.0 h1:jNKW89nPf0vR0EkjHG8Zz16h6p3zqwYEOxl github.com/cosmos/ledger-cosmos-go v1.0.0/go.mod h1:mGaw2wDOf+Z6SfRJsMGxU9DIrBa4du0MAiPlpPhLAOE= 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.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo= +github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/crate-crypto/go-eth-kzg v1.5.0 h1:FYRiJMJG2iv+2Dy3fi14SVGjcPteZ5HAAUe4YWlJygc= github.com/crate-crypto/go-eth-kzg v1.5.0/go.mod h1:J9/u5sWfznSObptgfa92Jq8rTswn6ahQWEuiLHOjCUI= github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a h1:W8mUrRp6NOVl3J+MYp5kPMoUZPp7aOYHtaua31lwRHg= @@ -873,8 +874,8 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k github.com/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI= github.com/mattn/go-isatty v0.0.24/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mholt/archives v0.1.5 h1:Fh2hl1j7VEhc6DZs2DLMgiBNChUux154a1G+2esNvzQ= github.com/mholt/archives v0.1.5/go.mod h1:3TPMmBLPsgszL+1As5zECTuKwKvIfj6YcwWPpeTAXF4= @@ -1056,6 +1057,7 @@ github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4 github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pion/datachannel v1.5.10 h1:ly0Q26K1i6ZkGf42W7D4hQYR90pZwzFOjTq5AuCKk4o= github.com/pion/datachannel v1.5.10/go.mod h1:p/jJfC9arb29W7WrxyKbepTU20CFgyx5oLo8Rs4Py/M= +github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s= github.com/pion/dtls/v2 v2.2.12 h1:KP7H5/c1EiVAAKUmXyCzPiQe5+bCJrpOeKg/L05dunk= github.com/pion/dtls/v2 v2.2.12/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE= github.com/pion/dtls/v3 v3.1.2 h1:gqEdOUXLtCGW+afsBLO0LtDD8GnuBBjEy6HRtyofZTc= @@ -1064,6 +1066,7 @@ github.com/pion/ice/v4 v4.0.10 h1:P59w1iauC/wPk9PdY8Vjl4fOFL5B+USq1+xbDcN6gT4= github.com/pion/ice/v4 v4.0.10/go.mod h1:y3M18aPhIxLlcO/4dn9X8LzLLSma84cx6emMSu14FGw= github.com/pion/interceptor v0.1.40 h1:e0BjnPcGpr2CFQgKhrQisBU7V3GXK6wrfYrGYaU6Jq4= github.com/pion/interceptor v0.1.40/go.mod h1:Z6kqH7M/FYirg3frjGJ21VLSRJGBXB/KqaTIrdqnOic= +github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= github.com/pion/logging v0.2.4 h1:tTew+7cmQ+Mc1pTBLKH2puKsOvhm32dROumOZ655zB8= github.com/pion/logging v0.2.4/go.mod h1:DffhXTKYdNZU+KtJ5pyQDjvOAh/GsNSyv1lbkFbe3so= github.com/pion/mdns/v2 v2.0.7 h1:c9kM8ewCgjslaAmicYMFQIde2H9/lrZpjBkN8VwoVtM= @@ -1080,13 +1083,15 @@ github.com/pion/sdp/v3 v3.0.18 h1:l0bAXazKHpepazVdp+tPYnrsy9dfh7ZbT8DxesH5ZnI= github.com/pion/sdp/v3 v3.0.18/go.mod h1:ZREGo6A9ZygQ9XkqAj5xYCQtQpif0i6Pa81HOiAdqQ8= github.com/pion/srtp/v3 v3.0.6 h1:E2gyj1f5X10sB/qILUGIkL4C2CqK269Xq167PbGCc/4= github.com/pion/srtp/v3 v3.0.6/go.mod h1:BxvziG3v/armJHAaJ87euvkhHqWe9I7iiOy50K2QkhY= -github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4= github.com/pion/stun/v2 v2.0.0 h1:A5+wXKLAypxQri59+tmQKVs7+l6mMM+3d+eER9ifRU0= github.com/pion/stun/v2 v2.0.0/go.mod h1:22qRSh08fSEttYUmJZGlriq9+03jtVmXNODgLccj8GQ= github.com/pion/stun/v3 v3.1.2 h1:86IhD8wFn6IDW4b1/0QzoQS+f5PeA8OHHRn8UZW5ErY= github.com/pion/stun/v3 v3.1.2/go.mod h1:H7gDic7nNwlUL05pbs6T1dtaBehh/KjupxfWw3ZI7cA= +github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g= +github.com/pion/transport/v2 v2.2.4/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0= github.com/pion/transport/v2 v2.2.10 h1:ucLBLE8nuxiHfvkFKnkDQRYWYfp8ejf4YBOPfaQpw6Q= github.com/pion/transport/v2 v2.2.10/go.mod h1:sq1kSLWs+cHW9E+2fJP95QudkzbK7wscs8yYgQToO5E= +github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0= github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0= github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo= github.com/pion/transport/v4 v4.0.1 h1:sdROELU6BZ63Ab7FrOLn13M6YdJLY20wldXW2Cu2k8o= @@ -1267,6 +1272,7 @@ 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.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE= @@ -1311,13 +1317,13 @@ github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oW github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY= github.com/ulikunitz/xz v0.5.15/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.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= -github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= +github.com/urfave/cli/v2 v2.27.6 h1:VdRdS98FNhKZ8/Az8B7MTyGQmpIr36O1EHybx/LaZ4g= +github.com/urfave/cli/v2 v2.27.6/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/wlynxg/anet v0.0.3/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU= github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= @@ -1480,6 +1486,9 @@ golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw= golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1517,6 +1526,7 @@ 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.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.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ= golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1559,7 +1569,12 @@ golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE= golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1580,6 +1595,7 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ 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-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek= golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1650,6 +1666,10 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/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.7.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.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= @@ -1660,6 +1680,10 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0= golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1671,6 +1695,9 @@ 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.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs= golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1724,6 +1751,7 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 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.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.47.0 h1:7Kn5x/d1svx/PzryTsqeoZN4TZwqeH5pGWjefhLi/1Q= golang.org/x/tools v0.47.0/go.mod h1:dFHnyTvFWY212G+h7ZY4Vsp/K3U4/7W9TyVaAul8uCA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/e2e/interchaintestv8/ibc_eureka_test.go b/e2e/interchaintestv8/ibc_eureka_test.go index 83b8968ac..c4ce49eca 100644 --- a/e2e/interchaintestv8/ibc_eureka_test.go +++ b/e2e/interchaintestv8/ibc_eureka_test.go @@ -184,7 +184,11 @@ func (s *IbcEurekaTestSuite) SetupSuite(ctx context.Context, proofType types.Sup s.solidityFixtureGenerator = types.NewSolidityFixtureGenerator() s.Require().True(s.Run("Deploy IBC contracts", func() { - stdout, err := eth.ForgeScript(s.deployer, testvalues.E2EDeployScriptPath) + var forgeArgs []string + if os.Getenv(testvalues.EnvKeyEthTestnetType) == testvalues.EthTestnetTypeBesuQBFT { + forgeArgs = []string{"--slow"} + } + stdout, err := eth.ForgeScript(s.deployer, testvalues.E2EDeployScriptPath, forgeArgs...) s.Require().NoError(err) s.contractAddresses, err = ethereum.GetEthContractsFromDeployOutput(string(stdout)) diff --git a/e2e/interchaintestv8/proofapi/builder.go b/e2e/interchaintestv8/proofapi/builder.go index dedd4fc4d..5a4c2fbcb 100644 --- a/e2e/interchaintestv8/proofapi/builder.go +++ b/e2e/interchaintestv8/proofapi/builder.go @@ -104,11 +104,12 @@ func (b *ConfigBuilder) EthToCosmosAttested(p EthToCosmosAttestedParams) *Config SrcChain: p.EthChainID, DstChain: p.CosmosChainID, Config: EthToCosmosModuleConfig{ - Ics26Address: p.ICS26Address, - TmRpcUrl: p.TmRPC, - EthRpcUrl: p.EthRPC, - SignerAddress: p.SignerAddress, - Mode: AttestedMode{Config: aggConfig}, + Ics26Address: p.ICS26Address, + TmRpcUrl: p.TmRPC, + EthRpcUrl: p.EthRPC, + EthBeaconApiUrl: "", + SignerAddress: p.SignerAddress, + Mode: AttestedMode{Config: aggConfig}, }, } b.modules = append(b.modules, module) @@ -237,6 +238,39 @@ func (b *ConfigBuilder) EthToEthAttested(p EthToEthAttestedParams) *ConfigBuilde return b } +// ============================================================================= +// Besu → EVM +// ============================================================================= + +// BesuToEthParams contains parameters for besu_to_eth module. +type BesuToEthParams struct { + SrcChainID string + DstChainID string + SrcRPC string + DstRPC string + SrcICS26 string + DstICS26 string + ConsensusType string +} + +// BesuToEth adds a Besu→EVM module. +func (b *ConfigBuilder) BesuToEth(p BesuToEthParams) *ConfigBuilder { + module := ModuleConfig{ + Name: ModuleBesuToEth, + SrcChain: p.SrcChainID, + DstChain: p.DstChainID, + Config: BesuToEthModuleConfig{ + SrcRPCURL: p.SrcRPC, + SrcICS26Address: p.SrcICS26, + DstRPCURL: p.DstRPC, + DstICS26Address: p.DstICS26, + ConsensusType: p.ConsensusType, + }, + } + b.modules = append(b.modules, module) + return b +} + // ============================================================================= // Cosmos → Cosmos // ============================================================================= diff --git a/e2e/interchaintestv8/proofapi/builder_test.go b/e2e/interchaintestv8/proofapi/builder_test.go index bcc1dcfbe..a2ddaeda9 100644 --- a/e2e/interchaintestv8/proofapi/builder_test.go +++ b/e2e/interchaintestv8/proofapi/builder_test.go @@ -7,25 +7,26 @@ import ( "testing" ) -func TestEthToEthBuilderUsesRoutedSourceChain(t *testing.T) { - b := NewConfigBuilder().EthToEthAttested(EthToEthAttestedParams{ - SrcChainID: "eth-a", - DstChainID: "eth-b", - }) - module := b.modules[0] +func TestEVMToEVMBuildersEmitSourceChainOnlyAtRoutingLevel(t *testing.T) { + b := NewConfigBuilder(). + EthToEthAttested(EthToEthAttestedParams{SrcChainID: "eth-a", DstChainID: "eth-b"}). + BesuToEth(BesuToEthParams{SrcChainID: "besu-a", DstChainID: "besu-b"}) + wantSource := map[string]string{ModuleEthToEth: "eth-a", ModuleBesuToEth: "besu-a"} - config, err := json.Marshal(module.Config) - if err != nil { - t.Fatal(err) - } - var fields map[string]any - if err := json.Unmarshal(config, &fields); err != nil { - t.Fatal(err) - } - if _, ok := fields["src_chain_id"]; ok { - t.Error("module config contains obsolete src_chain_id") - } - if module.SrcChain != "eth-a" { - t.Errorf("routing src_chain = %q, want eth-a", module.SrcChain) + for _, module := range b.modules { + config, err := json.Marshal(module.Config) + if err != nil { + t.Fatal(err) + } + var fields map[string]any + if err := json.Unmarshal(config, &fields); err != nil { + t.Fatal(err) + } + if _, ok := fields["src_chain_id"]; ok { + t.Errorf("%s config contains obsolete src_chain_id", module.Name) + } + if module.SrcChain != wantSource[module.Name] { + t.Errorf("%s routing src_chain = %q, want %q", module.Name, module.SrcChain, wantSource[module.Name]) + } } } diff --git a/e2e/interchaintestv8/proofapi/config.go b/e2e/interchaintestv8/proofapi/config.go index fca6c89d0..28dceeca5 100644 --- a/e2e/interchaintestv8/proofapi/config.go +++ b/e2e/interchaintestv8/proofapi/config.go @@ -9,7 +9,6 @@ import ( "math/rand" "net" "os" - "text/template" "time" "github.com/srdtrk/solidity-ibc-eureka/e2e/v8/testvalues" @@ -21,6 +20,7 @@ const ( ModuleEthToCosmos = "eth_to_cosmos" ModuleEthToCosmosCompat = "eth_to_cosmos_compat" ModuleEthToEth = "eth_to_eth" + ModuleBesuToEth = "besu_to_eth" ModuleSolanaToCosmos = "solana_to_cosmos" ModuleCosmosToSolana = "cosmos_to_solana" ModuleEthToSolana = "eth_to_solana" @@ -148,43 +148,19 @@ func NewConfig(modules []ModuleConfig) Config { } } -// GenerateConfig creates a config from the template +// GenerateConfigFile writes the config as JSON. func (c *Config) GenerateConfigFile(filePath string) error { - tmpl, err := template.ParseFiles("e2e/interchaintestv8/proofapi/config.tmpl") - if err != nil { - return err + config := *c + if config.Modules == nil { + config.Modules = []ModuleConfig{} } - f, err := os.Create(filePath) + contents, err := json.MarshalIndent(config, "", " ") if err != nil { return err } - defer f.Close() - - return tmpl.Execute(f, c) -} -// ToJSON converts a ModuleConfig to JSON string - designed for use in templates -func (mc ModuleConfig) ToJSON() string { - jsonBytes, err := json.MarshalIndent(mc, "", " ") - if err != nil { - return fmt.Sprintf("\"Error generating JSON: %s\"", err) - } - return string(jsonBytes) -} - -// ModulesToJSON converts a slice of ModuleConfig to a JSON string -func ModulesToJSON(modules []ModuleConfig) (string, error) { - if len(modules) == 0 { - return "[]", nil - } - - jsonBytes, err := json.MarshalIndent(modules, "", " ") - if err != nil { - return "", fmt.Errorf("failed to marshal modules to JSON: %w", err) - } - - return string(jsonBytes), nil + return os.WriteFile(filePath, append(contents, '\n'), 0o600) } // EthToCosmosModuleConfig represents the configuration for eth_to_cosmos module @@ -254,6 +230,15 @@ type EthToEthModuleConfig struct { Mode TxBuilderMode `json:"mode"` } +// BesuToEthModuleConfig represents the configuration for besu_to_eth module. +type BesuToEthModuleConfig struct { + SrcRPCURL string `json:"src_rpc_url"` + SrcICS26Address string `json:"src_ics26_address"` + DstRPCURL string `json:"dst_rpc_url"` + DstICS26Address string `json:"dst_ics26_address"` + ConsensusType string `json:"consensus_type"` +} + // AttestorConfig represents the attestor configuration section type AttestorConfig struct { AttestorQueryTimeoutMs int `json:"attestor_query_timeout_ms"` diff --git a/e2e/interchaintestv8/proofapi/config.tmpl b/e2e/interchaintestv8/proofapi/config.tmpl deleted file mode 100644 index bf040c03b..000000000 --- a/e2e/interchaintestv8/proofapi/config.tmpl +++ /dev/null @@ -1,18 +0,0 @@ -{ - "modules": [ - {{- range $index, $module := .Modules }} - {{- if $index }},{{ end }} - {{ $module.ToJSON }} - {{- end }} - ], - "server": { - "address": "{{ .Server.Address }}", - "port": {{ .Server.Port }} - }, - "observability": { - "level": "{{ .Observability.Level }}", - "use_otel": {{ .Observability.UseOtel }}, - "service_name": "{{ .Observability.ServiceName }}"{{ if .Observability.OTelEndpoint }}, - "otel_endpoint": "{{ .Observability.OTelEndpoint }}"{{ end }} - } -} diff --git a/e2e/interchaintestv8/proofapi/config_test.go b/e2e/interchaintestv8/proofapi/config_test.go new file mode 100644 index 000000000..7c511a431 --- /dev/null +++ b/e2e/interchaintestv8/proofapi/config_test.go @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: Apache-2.0 + +package proofapi + +import ( + "bytes" + "os" + "path/filepath" + "testing" +) + +func TestGenerateConfigFileEscapesStringsAndWritesEmptyModules(t *testing.T) { + path := filepath.Join(t.TempDir(), "config.json") + config := Config{Server: ServerConfig{Address: "quoted \"address\""}} + + if err := config.GenerateConfigFile(path); err != nil { + t.Fatal(err) + } + contents, err := os.ReadFile(path) + if err != nil { + t.Fatal(err) + } + if !bytes.Contains(contents, []byte(`"modules": []`)) { + t.Errorf("config contains non-empty or null modules: %s", contents) + } + if !bytes.Contains(contents, []byte(`"address": "quoted \"address\""`)) { + t.Errorf("config does not escape address: %s", contents) + } +} diff --git a/e2e/interchaintestv8/testvalues/values.go b/e2e/interchaintestv8/testvalues/values.go index e579d6d12..253d060e9 100644 --- a/e2e/interchaintestv8/testvalues/values.go +++ b/e2e/interchaintestv8/testvalues/values.go @@ -58,6 +58,8 @@ const ( EnvKeyGenerateWasmFixtures = "GENERATE_WASM_FIXTURES" // EnvKeyGenerateTendermintLightClientFixtures Generate fixtures for the tendermint light client tests if set to true. EnvKeyGenerateTendermintLightClientFixtures = "GENERATE_TENDERMINT_LIGHT_CLIENT_FIXTURES" + // EnvKeyGenerateBesuLightClientFixtures Generate fixtures for the Besu light client tests if set to true. + EnvKeyGenerateBesuLightClientFixtures = "GENERATE_BESU_LIGHT_CLIENT_FIXTURES" // The log level for the Rust logger. EnvKeyRustLog = "RUST_LOG" @@ -94,6 +96,9 @@ const ( // EthTestnetTypePoS uses Kurtosis for full PoS infrastructure with beacon chain EthTestnetTypePoS = "pos" + // EthTestnetTypeBesuQBFT uses a real 4-validator Besu QBFT network + EthTestnetTypeBesuQBFT = "besu-qbft" + // EthTestnetType_None disables Ethereum chain setup EthTestnetType_None = "none" @@ -109,7 +114,7 @@ const ( // Attestor light client (for Cosmos verification on Ethereum) CosmosLcTypeAttestor = "attestor" - // EnvKeyEthTestnetType The Ethereum testnet type (anvil|pos). + // EnvKeyEthTestnetType The Ethereum testnet type (anvil|pos|besu-qbft|none). EnvKeyEthTestnetType = "ETH_TESTNET_TYPE" // EnvKeyEthAnvilCount Number of Anvil chains to create (only when ETH_TESTNET_TYPE=anvil). Defaults to 1. EnvKeyEthAnvilCount = "ETH_ANVIL_COUNT" @@ -197,6 +202,10 @@ const ( SolanaLedgerDir = "test-ledger" // TendermintLightClientFixturesDir is the directory where the Tendermint light client fixtures are stored. TendermintLightClientFixturesDir = "packages/tendermint-light-client/fixtures/" + // BesuBFTFixturesDir is the directory where the Besu BFT light client fixtures are stored. + // Relative to the repo root (e2e suites chdir there), and shared with the Foundry suite in + // ibc-solidity/test/besu-bft (which resolves it via vm.projectRoot()). + BesuBFTFixturesDir = "ibc-solidity/test/besu-bft/fixtures" // IbcCommitmentSlotHex is the storage slot in the IBC solidity contract for the IBC commitments. IbcCommitmentSlotHex = ics26router.IbcStoreStorageSlot @@ -229,8 +238,12 @@ const ( ParameterKey_Sp1Verifier = "sp1_verifier" // Zk algorithm parameter key for the proof API's sp1 light client creation. ParameterKey_ZkAlgorithm = "zk_algorithm" - // The role manager address parameter key for the proof API's sp1 light client creation. + // The role manager address parameter key for proof API light client creation. ParameterKey_RoleManager = "role_manager" + // Trusting period parameter key for proof API light client creation. + ParameterKey_TrustingPeriod = "trusting_period" + // Max clock drift parameter key for proof API light client creation. + ParameterKey_MaxClockDrift = "max_clock_drift" // Checksum hex parameter key for the proof API's ethereum light client creation. ParameterKey_ChecksumHex = "checksum_hex" diff --git a/e2e/interchaintestv8/types/besu_fixtures.go b/e2e/interchaintestv8/types/besu_fixtures.go new file mode 100644 index 000000000..2303e7e85 --- /dev/null +++ b/e2e/interchaintestv8/types/besu_fixtures.go @@ -0,0 +1,709 @@ +// SPDX-License-Identifier: Apache-2.0 + +package types + +import ( + "context" + "crypto/ecdsa" + "encoding/hex" + "encoding/json" + "fmt" + "math/big" + "os" + "path/filepath" + "strings" + + ethcommon "github.com/ethereum/go-ethereum/common" + gethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient/gethclient" + "github.com/ethereum/go-ethereum/rlp" + + channeltypesv2 "github.com/cosmos/ibc-go/v11/modules/core/04-channel/v2/types" + ibchostv2 "github.com/cosmos/ibc-go/v11/modules/core/24-host/v2" + + "github.com/cosmos/solidity-ibc-eureka/packages/go-abigen/ics26router" + + "github.com/srdtrk/solidity-ibc-eureka/e2e/v8/ethereum" + "github.com/srdtrk/solidity-ibc-eureka/e2e/v8/testvalues" +) + +type BesuFixtureGenerator struct { + Enabled bool +} + +type GenerateQBFTFixtureParams struct { + SourceChain *ethereum.Ethereum + RouterAddress ethcommon.Address + Packet ics26router.IICS26RouterMsgsPacket + InitialTrustedHeight uint64 + AdjacentUpdateHeight uint64 + NonAdjacentUpdateHeight uint64 + SyntheticSourceHeight uint64 + TrustingPeriod uint64 + MaxClockDrift uint64 +} + +type besuFixture struct { + RouterAddress string `json:"routerAddress"` + InitialTrustedHeight uint64 `json:"initialTrustedHeight"` + InitialTrustedTimestamp uint64 `json:"initialTrustedTimestamp"` + InitialTrustedStorageRoot string `json:"initialTrustedStorageRoot"` + InitialTrustedValidators []string `json:"initialTrustedValidators"` + TrustingPeriod uint64 `json:"trustingPeriod"` + MaxClockDrift uint64 `json:"maxClockDrift"` + AdjacentUpdate besuUpdateFixture `json:"adjacentUpdate"` + NonAdjacentUpdate besuUpdateFixture `json:"nonAdjacentUpdate"` + LowQuorumUpdate besuRejectionUpdateFixture `json:"lowQuorumUpdate"` + ConflictingUpdate besuRejectionUpdateFixture `json:"conflictingUpdate"` + LowOverlapUpdate besuRejectionUpdateFixture `json:"lowOverlapUpdate"` + Membership besuProofFixture `json:"membership"` + NonMembership besuProofFixture `json:"nonMembership"` +} + +type besuUpdateFixture struct { + Height uint64 `json:"height"` + HeaderRlp string `json:"headerRlp"` + TrustedHeight uint64 `json:"trustedHeight"` + AccountProof string `json:"accountProof"` + ExpectedTimestamp uint64 `json:"expectedTimestamp"` + ExpectedStorageRoot string `json:"expectedStorageRoot"` + ExpectedValidators []string `json:"expectedValidators"` +} + +type besuRejectionUpdateFixture struct { + Height uint64 `json:"height"` + HeaderRlp string `json:"headerRlp"` + TrustedHeight uint64 `json:"trustedHeight"` + AccountProof string `json:"accountProof"` +} + +type besuProofFixture struct { + Proof string `json:"proof"` + ProofHeight uint64 `json:"proofHeight"` + Path string `json:"path"` + Value string `json:"value,omitempty"` + ExpectedTimestamp uint64 `json:"expectedTimestamp"` +} + +type liveHeader struct { + Header *gethtypes.Header + HeaderRLP []byte + Validators []ethcommon.Address +} + +type mutableQBFTHeader struct { + items []rlp.RawValue + extraItems []rlp.RawValue +} + +var syntheticLowOverlapValidatorKeys = []string{ + "59c6995e998f97a5a0044966f094538f8e0f1c7f6d0bdf5f4b4a0d5c8fba8f5a", + "5de4111a39c2d6f5f2f1df6b0ad72037d399a8ce28b5c82853453ea50ccaa43d", + "7c852118294c1ec93b7d4c7d4b3f3b2d8f5f1e6d5c4b3a291817161514131211", +} + +func NewBesuFixtureGenerator() *BesuFixtureGenerator { + return &BesuFixtureGenerator{ + Enabled: os.Getenv(testvalues.EnvKeyGenerateBesuLightClientFixtures) == testvalues.EnvValueGenerateFixtures_True, + } +} + +func (g *BesuFixtureGenerator) GenerateAndSaveQBFTFixture(ctx context.Context, params GenerateQBFTFixtureParams) error { + if !g.Enabled { + return nil + } + + fixture, err := generateQBFTFixture(ctx, params) + if err != nil { + return err + } + + fixtureBz, err := json.MarshalIndent(fixture, "", " ") + if err != nil { + return err + } + + fixturePath := filepath.Join(testvalues.BesuBFTFixturesDir, "qbft.json") + // The checked-in fixture is intentionally readable by all test processes. + return os.WriteFile(fixturePath, fixtureBz, 0o644) //nolint:gosec +} + +func generateQBFTFixture(ctx context.Context, params GenerateQBFTFixtureParams) (besuFixture, error) { + if params.SourceChain == nil { + return besuFixture{}, fmt.Errorf("missing source chain") + } + if params.InitialTrustedHeight == 0 { + return besuFixture{}, fmt.Errorf("initial trusted height must be greater than zero") + } + if params.AdjacentUpdateHeight <= params.InitialTrustedHeight || params.AdjacentUpdateHeight-params.InitialTrustedHeight != 1 { + return besuFixture{}, fmt.Errorf("adjacent update height must equal initial trusted height plus one") + } + if params.NonAdjacentUpdateHeight <= params.AdjacentUpdateHeight { + return besuFixture{}, fmt.Errorf("non-adjacent update height must be greater than adjacent update height") + } + if params.SyntheticSourceHeight <= params.NonAdjacentUpdateHeight { + return besuFixture{}, fmt.Errorf("synthetic source height must be greater than non-adjacent update height") + } + + trustedHeader, err := fetchLiveHeader(ctx, params.SourceChain, params.InitialTrustedHeight) + if err != nil { + return besuFixture{}, err + } + nonAdjacentHeader, err := fetchLiveHeader(ctx, params.SourceChain, params.NonAdjacentUpdateHeight) + if err != nil { + return besuFixture{}, err + } + syntheticSourceHeader, err := fetchLiveHeader(ctx, params.SourceChain, params.SyntheticSourceHeight) + if err != nil { + return besuFixture{}, err + } + + validatorKeys, err := loadQBFTValidatorKeys() + if err != nil { + return besuFixture{}, err + } + + trustedProof, _, err := fetchAccountProof(ctx, params.SourceChain, params.RouterAddress, params.InitialTrustedHeight) + if err != nil { + return besuFixture{}, err + } + adjacentUpdate, err := buildLiveUpdateFixture(ctx, params.SourceChain, params.RouterAddress, params.InitialTrustedHeight, params.AdjacentUpdateHeight) + if err != nil { + return besuFixture{}, err + } + nonAdjacentUpdate, err := buildLiveUpdateFixture(ctx, params.SourceChain, params.RouterAddress, params.InitialTrustedHeight, params.NonAdjacentUpdateHeight) + if err != nil { + return besuFixture{}, err + } + lowQuorumUpdate, err := buildLowQuorumFixture(nonAdjacentUpdate, nonAdjacentHeader) + if err != nil { + return besuFixture{}, err + } + conflictingUpdate, err := buildConflictingFixture( + ctx, + params.InitialTrustedHeight, + nonAdjacentUpdate.Height, + syntheticSourceHeader, + validatorKeys, + params.SourceChain, + params.RouterAddress, + ) + if err != nil { + return besuFixture{}, err + } + lowOverlapUpdate, err := buildLowOverlapFixture( + params.InitialTrustedHeight, + nonAdjacentUpdate.Height+1, + syntheticSourceHeader, + validatorKeys, + ) + if err != nil { + return besuFixture{}, err + } + membership, err := buildMembershipFixture(ctx, params.SourceChain, params.RouterAddress, params.Packet, params.NonAdjacentUpdateHeight, nonAdjacentHeader.Header.Time) + if err != nil { + return besuFixture{}, err + } + nonMembership, err := buildNonMembershipFixture(ctx, params.SourceChain, params.RouterAddress, params.Packet, params.NonAdjacentUpdateHeight, nonAdjacentHeader.Header.Time) + if err != nil { + return besuFixture{}, err + } + + return besuFixture{ + RouterAddress: params.RouterAddress.Hex(), + InitialTrustedHeight: params.InitialTrustedHeight, + InitialTrustedTimestamp: trustedHeader.Header.Time, + InitialTrustedStorageRoot: trustedProof.StorageHash.Hex(), + InitialTrustedValidators: addressesToHex(trustedHeader.Validators), + TrustingPeriod: params.TrustingPeriod, + MaxClockDrift: params.MaxClockDrift, + AdjacentUpdate: adjacentUpdate, + NonAdjacentUpdate: nonAdjacentUpdate, + LowQuorumUpdate: lowQuorumUpdate, + ConflictingUpdate: conflictingUpdate, + LowOverlapUpdate: lowOverlapUpdate, + Membership: membership, + NonMembership: nonMembership, + }, nil +} + +func buildLiveUpdateFixture( + ctx context.Context, + chain *ethereum.Ethereum, + routerAddress ethcommon.Address, + trustedHeight uint64, + targetHeight uint64, +) (besuUpdateFixture, error) { + header, err := fetchLiveHeader(ctx, chain, targetHeight) + if err != nil { + return besuUpdateFixture{}, err + } + proof, accountProofRLP, err := fetchAccountProof(ctx, chain, routerAddress, targetHeight) + if err != nil { + return besuUpdateFixture{}, err + } + + return besuUpdateFixture{ + Height: targetHeight, + HeaderRlp: encodeHex(header.HeaderRLP), + TrustedHeight: trustedHeight, + AccountProof: encodeHex(accountProofRLP), + ExpectedTimestamp: header.Header.Time, + ExpectedStorageRoot: proof.StorageHash.Hex(), + ExpectedValidators: addressesToHex(header.Validators), + }, nil +} + +func buildLowQuorumFixture(update besuUpdateFixture, header liveHeader) (besuRejectionUpdateFixture, error) { + mutable, err := decodeMutableQBFTHeader(header.HeaderRLP) + if err != nil { + return besuRejectionUpdateFixture{}, err + } + commitSeals, err := mutable.commitSeals() + if err != nil { + return besuRejectionUpdateFixture{}, err + } + if len(commitSeals) < 2 { + return besuRejectionUpdateFixture{}, fmt.Errorf("expected at least two commit seals, got %d", len(commitSeals)) + } + mutable.setCommitSeals(commitSeals[:2]) + mutatedHeader, err := mutable.encode() + if err != nil { + return besuRejectionUpdateFixture{}, err + } + + return besuRejectionUpdateFixture{ + Height: update.Height, + HeaderRlp: encodeHex(mutatedHeader), + TrustedHeight: update.TrustedHeight, + AccountProof: "0x", + }, nil +} + +func buildConflictingFixture( + ctx context.Context, + trustedHeight uint64, + targetHeight uint64, + baseHeader liveHeader, + validatorKeys map[ethcommon.Address]*ecdsa.PrivateKey, + chain *ethereum.Ethereum, + routerAddress ethcommon.Address, +) (besuRejectionUpdateFixture, error) { + mutable, err := decodeMutableQBFTHeader(baseHeader.HeaderRLP) + if err != nil { + return besuRejectionUpdateFixture{}, err + } + mutable.setHeight(targetHeight) + validators, err := mutable.validators() + if err != nil { + return besuRejectionUpdateFixture{}, err + } + signerKeys, err := signerKeysFor(validators[:3], validatorKeys) + if err != nil { + return besuRejectionUpdateFixture{}, err + } + mutable.setCommitSeals(signQBFTCommitSeals(mutable, signerKeys)) + mutatedHeader, err := mutable.encode() + if err != nil { + return besuRejectionUpdateFixture{}, err + } + + _, accountProofRLP, err := fetchAccountProof(ctx, chain, routerAddress, baseHeader.Header.Number.Uint64()) + if err != nil { + return besuRejectionUpdateFixture{}, err + } + + return besuRejectionUpdateFixture{ + Height: targetHeight, + HeaderRlp: encodeHex(mutatedHeader), + TrustedHeight: trustedHeight, + AccountProof: encodeHex(accountProofRLP), + }, nil +} + +func buildLowOverlapFixture( + trustedHeight uint64, + targetHeight uint64, + baseHeader liveHeader, + validatorKeys map[ethcommon.Address]*ecdsa.PrivateKey, +) (besuRejectionUpdateFixture, error) { + mutable, err := decodeMutableQBFTHeader(baseHeader.HeaderRLP) + if err != nil { + return besuRejectionUpdateFixture{}, err + } + mutable.setHeight(targetHeight) + + baseValidators, err := mutable.validators() + if err != nil { + return besuRejectionUpdateFixture{}, err + } + if len(baseValidators) == 0 { + return besuRejectionUpdateFixture{}, fmt.Errorf("missing base validators") + } + + syntheticKeys, err := loadSyntheticLowOverlapValidatorKeys() + if err != nil { + return besuRejectionUpdateFixture{}, err + } + lowOverlapValidators := []ethcommon.Address{ + baseValidators[0], + crypto.PubkeyToAddress(syntheticKeys[0].PublicKey), + crypto.PubkeyToAddress(syntheticKeys[1].PublicKey), + crypto.PubkeyToAddress(syntheticKeys[2].PublicKey), + } + mutable.setValidators(lowOverlapValidators) + + signerKeys, err := signerKeysFor([]ethcommon.Address{ + lowOverlapValidators[0], + lowOverlapValidators[1], + lowOverlapValidators[2], + }, mergeValidatorKeyMaps(validatorKeys, toKeyMap(syntheticKeys))) + if err != nil { + return besuRejectionUpdateFixture{}, err + } + mutable.setCommitSeals(signQBFTCommitSeals(mutable, signerKeys)) + mutatedHeader, err := mutable.encode() + if err != nil { + return besuRejectionUpdateFixture{}, err + } + + return besuRejectionUpdateFixture{ + Height: targetHeight, + HeaderRlp: encodeHex(mutatedHeader), + TrustedHeight: trustedHeight, + AccountProof: "0x", + }, nil +} + +func buildMembershipFixture( + ctx context.Context, + chain *ethereum.Ethereum, + routerAddress ethcommon.Address, + packet ics26router.IICS26RouterMsgsPacket, + proofHeight uint64, + expectedTimestamp uint64, +) (besuProofFixture, error) { + path := ibchostv2.PacketCommitmentKey(packet.SourceClient, packet.Sequence) + proofRLP, err := fetchStorageProof(ctx, chain, routerAddress, path, proofHeight) + if err != nil { + return besuProofFixture{}, err + } + + return besuProofFixture{ + Proof: encodeHex(proofRLP), + ProofHeight: proofHeight, + Path: encodeHex(path), + Value: encodeHex(packetCommitment(packet)), + ExpectedTimestamp: expectedTimestamp, + }, nil +} + +func buildNonMembershipFixture( + ctx context.Context, + chain *ethereum.Ethereum, + routerAddress ethcommon.Address, + packet ics26router.IICS26RouterMsgsPacket, + proofHeight uint64, + expectedTimestamp uint64, +) (besuProofFixture, error) { + path := ibchostv2.PacketReceiptKey(packet.DestClient, packet.Sequence) + proofRLP, err := fetchStorageProof(ctx, chain, routerAddress, path, proofHeight) + if err != nil { + return besuProofFixture{}, err + } + + return besuProofFixture{ + Proof: encodeHex(proofRLP), + ProofHeight: proofHeight, + Path: encodeHex(path), + ExpectedTimestamp: expectedTimestamp, + }, nil +} + +func fetchLiveHeader(ctx context.Context, chain *ethereum.Ethereum, height uint64) (liveHeader, error) { + header, err := chain.RPCClient.HeaderByNumber(ctx, newUint64(height)) + if err != nil { + return liveHeader{}, fmt.Errorf("fetch header at height %d: %w", height, err) + } + headerRLP, err := rlp.EncodeToBytes(header) + if err != nil { + return liveHeader{}, fmt.Errorf("encode header rlp at height %d: %w", height, err) + } + mutable, err := decodeMutableQBFTHeader(headerRLP) + if err != nil { + return liveHeader{}, fmt.Errorf("decode header at height %d: %w", height, err) + } + validators, err := mutable.validators() + if err != nil { + return liveHeader{}, fmt.Errorf("extract validators at height %d: %w", height, err) + } + + return liveHeader{ + Header: header, + HeaderRLP: headerRLP, + Validators: validators, + }, nil +} + +func fetchAccountProof( + ctx context.Context, + chain *ethereum.Ethereum, + routerAddress ethcommon.Address, + height uint64, +) (*gethclient.AccountResult, []byte, error) { + proof, err := gethclient.New(chain.RPCClient.Client()).GetProof(ctx, routerAddress, nil, newUint64(height)) + if err != nil { + return nil, nil, fmt.Errorf("fetch account proof at height %d: %w", height, err) + } + proofRLP, err := encodeProofNodes(proof.AccountProof) + if err != nil { + return nil, nil, fmt.Errorf("encode account proof at height %d: %w", height, err) + } + return proof, proofRLP, nil +} + +func fetchStorageProof( + ctx context.Context, + chain *ethereum.Ethereum, + routerAddress ethcommon.Address, + path []byte, + height uint64, +) ([]byte, error) { + storageKey := ethereum.GetCommitmentsStorageKey(path) + proof, err := gethclient.New(chain.RPCClient.Client()).GetProof(ctx, routerAddress, []string{storageKey.Hex()}, newUint64(height)) + if err != nil { + return nil, fmt.Errorf("fetch storage proof at height %d: %w", height, err) + } + if len(proof.StorageProof) != 1 { + return nil, fmt.Errorf("expected one storage proof at height %d, got %d", height, len(proof.StorageProof)) + } + proofRLP, err := encodeProofNodes(proof.StorageProof[0].Proof) + if err != nil { + return nil, fmt.Errorf("encode storage proof at height %d: %w", height, err) + } + return proofRLP, nil +} + +func encodeProofNodes(nodes []string) ([]byte, error) { + rawNodes := make([]rlp.RawValue, len(nodes)) + for i, node := range nodes { + rawNodes[i] = ethcommon.FromHex(node) + } + return rlp.EncodeToBytes(rawNodes) +} + +func packetCommitment(packet ics26router.IICS26RouterMsgsPacket) []byte { + payloads := make([]channeltypesv2.Payload, len(packet.Payloads)) + for i, payload := range packet.Payloads { + payloads[i] = channeltypesv2.Payload{ + SourcePort: payload.SourcePort, + DestinationPort: payload.DestPort, + Version: payload.Version, + Encoding: payload.Encoding, + Value: payload.Value, + } + } + return channeltypesv2.CommitPacket(channeltypesv2.Packet{ + Sequence: packet.Sequence, + SourceClient: packet.SourceClient, + DestinationClient: packet.DestClient, + TimeoutTimestamp: packet.TimeoutTimestamp, + Payloads: payloads, + }) +} + +func decodeMutableQBFTHeader(headerRLP []byte) (*mutableQBFTHeader, error) { + var items []rlp.RawValue + if err := rlp.DecodeBytes(headerRLP, &items); err != nil { + return nil, err + } + if len(items) < 15 { + return nil, fmt.Errorf("expected at least 15 header items, got %d", len(items)) + } + var extraData []byte + if err := rlp.DecodeBytes(items[12], &extraData); err != nil { + return nil, err + } + var extraItems []rlp.RawValue + if err := rlp.DecodeBytes(extraData, &extraItems); err != nil { + return nil, err + } + if len(extraItems) != 5 { + return nil, fmt.Errorf("expected 5 extraData items, got %d", len(extraItems)) + } + return &mutableQBFTHeader{items: items, extraItems: extraItems}, nil +} + +func (h *mutableQBFTHeader) encode() ([]byte, error) { + extraData, err := rlp.EncodeToBytes(h.extraItems) + if err != nil { + return nil, err + } + items := cloneRawValues(h.items) + items[12], err = rlp.EncodeToBytes(extraData) + if err != nil { + return nil, err + } + return rlp.EncodeToBytes(items) +} + +func (h *mutableQBFTHeader) validators() ([]ethcommon.Address, error) { + var validators []ethcommon.Address + if err := rlp.DecodeBytes(h.extraItems[1], &validators); err != nil { + return nil, err + } + return validators, nil +} + +func (h *mutableQBFTHeader) commitSeals() ([][]byte, error) { + var seals [][]byte + if err := rlp.DecodeBytes(h.extraItems[4], &seals); err != nil { + return nil, err + } + return seals, nil +} + +func (h *mutableQBFTHeader) setHeight(height uint64) { + h.items[8] = mustRLP(height) +} + +func (h *mutableQBFTHeader) setValidators(validators []ethcommon.Address) { + h.extraItems[1] = mustRLP(validators) +} + +func (h *mutableQBFTHeader) setCommitSeals(seals [][]byte) { + h.extraItems[4] = mustRLP(seals) +} + +func signQBFTCommitSeals(header *mutableQBFTHeader, keys []*ecdsa.PrivateKey) [][]byte { + digest := header.commitSealDigest() + seals := make([][]byte, len(keys)) + for i, key := range keys { + seal, err := crypto.Sign(digest.Bytes(), key) + if err != nil { + panic(err) + } + seals[i] = seal + } + return seals +} + +func (h *mutableQBFTHeader) commitSealDigest() ethcommon.Hash { + signingExtraItems := cloneRawValues(h.extraItems) + signingExtraItems[4] = rlp.RawValue{0xc0} + signingExtraData, err := rlp.EncodeToBytes(signingExtraItems) + if err != nil { + panic(err) + } + + items := cloneRawValues(h.items) + items[12], err = rlp.EncodeToBytes(signingExtraData) + if err != nil { + panic(err) + } + payload, err := rlp.EncodeToBytes(items) + if err != nil { + panic(err) + } + return crypto.Keccak256Hash(payload) +} + +func loadQBFTValidatorKeys() (map[ethcommon.Address]*ecdsa.PrivateKey, error) { + validatorKeyPaths := []string{ + "e2e/interchaintestv8/chainconfig/testdata/besu/qbft/keys/validator1/key", + "e2e/interchaintestv8/chainconfig/testdata/besu/qbft/keys/validator2/key", + "e2e/interchaintestv8/chainconfig/testdata/besu/qbft/keys/validator3/key", + "e2e/interchaintestv8/chainconfig/testdata/besu/qbft/keys/validator4/key", + } + + keys := make(map[ethcommon.Address]*ecdsa.PrivateKey, len(validatorKeyPaths)) + for _, keyPath := range validatorKeyPaths { + keyHex, err := os.ReadFile(keyPath) + if err != nil { + return nil, err + } + key, err := crypto.HexToECDSA(strings.TrimPrefix(strings.TrimSpace(string(keyHex)), "0x")) + if err != nil { + return nil, err + } + keys[crypto.PubkeyToAddress(key.PublicKey)] = key + } + return keys, nil +} + +func loadSyntheticLowOverlapValidatorKeys() ([]*ecdsa.PrivateKey, error) { + keys := make([]*ecdsa.PrivateKey, len(syntheticLowOverlapValidatorKeys)) + for i, keyHex := range syntheticLowOverlapValidatorKeys { + key, err := crypto.HexToECDSA(strings.TrimPrefix(keyHex, "0x")) + if err != nil { + return nil, err + } + keys[i] = key + } + return keys, nil +} + +func signerKeysFor(validators []ethcommon.Address, keyMap map[ethcommon.Address]*ecdsa.PrivateKey) ([]*ecdsa.PrivateKey, error) { + keys := make([]*ecdsa.PrivateKey, len(validators)) + for i, validator := range validators { + key, ok := keyMap[validator] + if !ok { + return nil, fmt.Errorf("missing validator key for %s", validator.Hex()) + } + keys[i] = key + } + return keys, nil +} + +func toKeyMap(keys []*ecdsa.PrivateKey) map[ethcommon.Address]*ecdsa.PrivateKey { + out := make(map[ethcommon.Address]*ecdsa.PrivateKey, len(keys)) + for _, key := range keys { + out[crypto.PubkeyToAddress(key.PublicKey)] = key + } + return out +} + +func mergeValidatorKeyMaps( + primary map[ethcommon.Address]*ecdsa.PrivateKey, + secondary map[ethcommon.Address]*ecdsa.PrivateKey, +) map[ethcommon.Address]*ecdsa.PrivateKey { + out := make(map[ethcommon.Address]*ecdsa.PrivateKey, len(primary)+len(secondary)) + for address, key := range primary { + out[address] = key + } + for address, key := range secondary { + out[address] = key + } + return out +} + +func cloneRawValues(values []rlp.RawValue) []rlp.RawValue { + cloned := make([]rlp.RawValue, len(values)) + copy(cloned, values) + return cloned +} + +func mustRLP(value interface{}) rlp.RawValue { + encoded, err := rlp.EncodeToBytes(value) + if err != nil { + panic(err) + } + return encoded +} + +func addressesToHex(addresses []ethcommon.Address) []string { + encoded := make([]string, len(addresses)) + for i, address := range addresses { + encoded[i] = address.Hex() + } + return encoded +} + +func encodeHex(value []byte) string { + return "0x" + hex.EncodeToString(value) +} + +func newUint64(value uint64) *big.Int { + return new(big.Int).SetUint64(value) +} diff --git a/flake.lock b/flake.lock index 742236408..50a86c540 100644 --- a/flake.lock +++ b/flake.lock @@ -75,11 +75,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1778233390, - "narHash": "sha256-sqJDd+rJw6mjAptJbb7A77WDDOls4EFc+RzBjW3bGoc=", + "lastModified": 1787834231, + "narHash": "sha256-2X16fN53tx1HCQpd9NFXogrxlpZ/2b+lbZ8mUR0AAXo=", "owner": "shazow", "repo": "foundry.nix", - "rev": "f99fbd9a93b27bef982726ce1a4b76daa8e0a507", + "rev": "6406ab52f559a8686fd95a71c53f2b5410eb1412", "type": "github" }, "original": { @@ -92,7 +92,9 @@ "natlint": { "inputs": { "flake-utils": "flake-utils_3", - "nixpkgs": "nixpkgs_2", + "nixpkgs": [ + "nixpkgs" + ], "rust-overlay": "rust-overlay" }, "locked": { @@ -124,22 +126,6 @@ } }, "nixpkgs_2": { - "locked": { - "lastModified": 1748026106, - "narHash": "sha256-6m1Y3/4pVw1RWTsrkAK2VMYSzG4MMIj7sqUy7o8th1o=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "063f43f2dbdef86376cc29ad646c45c46e93234c", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_3": { "locked": { "lastModified": 1744536153, "narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=", @@ -155,13 +141,13 @@ "type": "github" } }, - "nixpkgs_4": { + "nixpkgs_3": { "locked": { - "lastModified": 1783776592, - "narHash": "sha256-UgCQzxeWI75XM8G+hPrPh+MKzEPjG3SpAj7dtqSbksA=", + "lastModified": 1787498568, + "narHash": "sha256-9i/VTdusq/+NM/tz+J1Re+ojkMB8MBf0QshnYfzHz30=", "owner": "nixos", "repo": "nixpkgs", - "rev": "e7a3ca8092b61ff85b6a45bf863ea2b2d6a661b3", + "rev": "56c02bc00adcf003215cc4bd996d6efaf4cff188", "type": "github" }, "original": { @@ -171,7 +157,7 @@ "type": "github" } }, - "nixpkgs_5": { + "nixpkgs_4": { "locked": { "lastModified": 1744536153, "narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=", @@ -192,7 +178,7 @@ "flake-utils": "flake-utils", "foundry": "foundry", "natlint": "natlint", - "nixpkgs": "nixpkgs_4", + "nixpkgs": "nixpkgs_3", "rust-overlay": "rust-overlay_2", "solc": "solc", "sp1": "sp1" @@ -200,7 +186,7 @@ }, "rust-overlay": { "inputs": { - "nixpkgs": "nixpkgs_3" + "nixpkgs": "nixpkgs_2" }, "locked": { "lastModified": 1748140821, @@ -218,14 +204,14 @@ }, "rust-overlay_2": { "inputs": { - "nixpkgs": "nixpkgs_5" + "nixpkgs": "nixpkgs_4" }, "locked": { - "lastModified": 1783921439, - "narHash": "sha256-DsSIQSRMrLOz40LrGZ03sp2RlJ9sz3wKpd8XPTOzXnw=", + "lastModified": 1787834454, + "narHash": "sha256-jXSvqn04IOecJCvSvl8+g3PsbDVNP6qKs6dKUs/b16k=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "e013376c32a8fcf07ddb6ec71739552bc118b7bd", + "rev": "dc2fd1acc537f3583744e1373597a5731ff7a6e3", "type": "github" }, "original": { @@ -243,11 +229,11 @@ "solc-macos-amd64-list-json": "solc-macos-amd64-list-json" }, "locked": { - "lastModified": 1777817996, - "narHash": "sha256-iI71iUhD7THLibl3w1JcQEhHmTwZMxChi70RTe33BAo=", + "lastModified": 1786461652, + "narHash": "sha256-+ClEiyzReHNF93b8TZMt5QePhjTraXnO9eukkl3Flec=", "owner": "hellwolf", "repo": "solc.nix", - "rev": "e3cf898cb804d5c0e5474b378a300fe8942e67d6", + "rev": "9b3df77eb12b9716f4783b802b4332bfbfa5b4f7", "type": "github" }, "original": { @@ -259,13 +245,13 @@ "solc-macos-amd64-list-json": { "flake": false, "locked": { - "narHash": "sha256-zzwwHA2qPotv7yp8mK7+y9BZhm7ytuFeCJVvKBBdBn4=", + "narHash": "sha256-Vfa5XmxKcrBfMdJX3nWo+s0YixtdZND6l4llwNp+Xl0=", "type": "file", - "url": "https://github.com/argotorg/solc-bin/raw/902dfaf/macosx-amd64/list.json" + "url": "https://github.com/argotorg/solc-bin/raw/97e2659/macosx-amd64/list.json" }, "original": { "type": "file", - "url": "https://github.com/argotorg/solc-bin/raw/902dfaf/macosx-amd64/list.json" + "url": "https://github.com/argotorg/solc-bin/raw/97e2659/macosx-amd64/list.json" } }, "sp1": { diff --git a/flake.nix b/flake.nix index 5a6e8ce32..eb4b55703 100644 --- a/flake.nix +++ b/flake.nix @@ -12,7 +12,10 @@ }; foundry.url = "github:shazow/foundry.nix/stable"; rust-overlay.url = "github:oxalica/rust-overlay"; - natlint.url = "github:srdtrk/natlint"; + natlint = { + url = "github:srdtrk/natlint"; + inputs.nixpkgs.follows = "nixpkgs"; + }; sp1 = { url = "github:vaporif/sp1-overlay"; inputs.nixpkgs.follows = "nixpkgs"; diff --git a/ibc-solana/AGENTS.md b/ibc-solana/AGENTS.md new file mode 100644 index 000000000..e9e809f7e --- /dev/null +++ b/ibc-solana/AGENTS.md @@ -0,0 +1,20 @@ +# AGENTS.md + +This subtree contains the Anchor-based Solana IBC programs and their ProgramTest integration harness. + +Look here first: +- `ibc-solana/README.md` +- `ibc-solana/Anchor.toml` +- `ibc-solana/Cargo.toml` +- `ibc-solana/integration-tests/README.md` + +Use the smallest relevant validation from the repo root: +- Build and refresh IDLs: `just solana::build-solana-programs` +- Solana unit tests: `just solana::test-solana` +- Anchor tests: `just solana::test-anchor-solana` +- Lint: `just solana::lint-solana` + +Local constraints: +- Prefer the repo `just` recipes over raw `anchor` commands; they auto-detect `anchor-nix` when available. +- If program interfaces or IDLs change, run `just solana::generate-solana-types`; do not hand-edit `packages/go-anchor/` except `packages/go-anchor/ics07_tendermint_patches/`, and do not hand-edit `e2e/interchaintestv8/solana/go-anchor/`. +- Cluster-specific program IDs live in `ibc-solana/Anchor.toml`, and keypairs live under `solana-keypairs//`; keep non-`localnet` keypairs out of git. diff --git a/ibc-solidity/abi/BesuIBFT2LightClient.json b/ibc-solidity/abi/BesuIBFT2LightClient.json new file mode 100644 index 000000000..b3b7b9852 --- /dev/null +++ b/ibc-solidity/abi/BesuIBFT2LightClient.json @@ -0,0 +1,763 @@ +[ + { + "type": "constructor", + "inputs": [ + { + "name": "ibcRouter", + "type": "address", + "internalType": "address" + }, + { + "name": "initialTrustedHeight", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "initialTrustedTimestamp", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "initialTrustedStorageRoot", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "initialTrustedValidators", + "type": "address[]", + "internalType": "address[]" + }, + { + "name": "trustingPeriod", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "maxClockDrift", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "roleManager", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "DEFAULT_ADMIN_ROLE", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "PROOF_SUBMITTER_ROLE", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getClientState", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes", + "internalType": "bytes" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getConsensusState", + "inputs": [ + { + "name": "revisionHeight", + "type": "uint64", + "internalType": "uint64" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes", + "internalType": "bytes" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getRoleAdmin", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "grantRole", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "hasRole", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "misbehaviour", + "inputs": [ + { + "name": "", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "view" + }, + { + "type": "function", + "name": "renounceRole", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "callerConfirmation", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "revokeRole", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "supportsInterface", + "inputs": [ + { + "name": "interfaceId", + "type": "bytes4", + "internalType": "bytes4" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "updateClient", + "inputs": [ + { + "name": "updateMsg", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [ + { + "name": "", + "type": "uint8", + "internalType": "enum ILightClientMsgs.UpdateResult" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "verifyMembership", + "inputs": [ + { + "name": "msg_", + "type": "tuple", + "internalType": "struct ILightClientMsgs.MsgVerifyMembership", + "components": [ + { + "name": "proof", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "proofHeight", + "type": "tuple", + "internalType": "struct IICS02ClientMsgs.Height", + "components": [ + { + "name": "revisionNumber", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "revisionHeight", + "type": "uint64", + "internalType": "uint64" + } + ] + }, + { + "name": "path", + "type": "bytes[]", + "internalType": "bytes[]" + }, + { + "name": "value", + "type": "bytes", + "internalType": "bytes" + } + ] + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "verifyNonMembership", + "inputs": [ + { + "name": "msg_", + "type": "tuple", + "internalType": "struct ILightClientMsgs.MsgVerifyNonMembership", + "components": [ + { + "name": "proof", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "proofHeight", + "type": "tuple", + "internalType": "struct IICS02ClientMsgs.Height", + "components": [ + { + "name": "revisionNumber", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "revisionHeight", + "type": "uint64", + "internalType": "uint64" + } + ] + }, + { + "name": "path", + "type": "bytes[]", + "internalType": "bytes[]" + } + ] + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "event", + "name": "RoleAdminChanged", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "previousAdminRole", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "newAdminRole", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "RoleGranted", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "sender", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "RoleRevoked", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "sender", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "error", + "name": "AccessControlBadConfirmation", + "inputs": [] + }, + { + "type": "error", + "name": "AccessControlUnauthorizedAccount", + "inputs": [ + { + "name": "account", + "type": "address", + "internalType": "address" + }, + { + "name": "neededRole", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "ConflictingConsensusState", + "inputs": [ + { + "name": "revisionHeight", + "type": "uint64", + "internalType": "uint64" + } + ] + }, + { + "type": "error", + "name": "ConsensusStateExpired", + "inputs": [ + { + "name": "trustedTimestamp", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "currentTimestamp", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "trustingPeriod", + "type": "uint64", + "internalType": "uint64" + } + ] + }, + { + "type": "error", + "name": "ConsensusStateNotFound", + "inputs": [ + { + "name": "revisionHeight", + "type": "uint64", + "internalType": "uint64" + } + ] + }, + { + "type": "error", + "name": "DuplicateCommitSealSigner", + "inputs": [ + { + "name": "signer", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "DuplicateValidator", + "inputs": [ + { + "name": "validator", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "EmptyValidatorSet", + "inputs": [] + }, + { + "type": "error", + "name": "HeaderFromFuture", + "inputs": [ + { + "name": "currentTimestamp", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "headerTimestamp", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "maxClockDrift", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "InsufficientTrustedValidatorOverlap", + "inputs": [ + { + "name": "actual", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "required", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "InsufficientValidatorQuorum", + "inputs": [ + { + "name": "actual", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "required", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "InvalidCommitSeal", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidCommitmentValue", + "inputs": [ + { + "name": "expectedValue", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "actualValue", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "InvalidDifficulty", + "inputs": [ + { + "name": "actualDifficulty", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "InvalidECDSASignatureLength", + "inputs": [ + { + "name": "length", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "InvalidExtraDataFormat", + "inputs": [ + { + "name": "itemsLength", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "InvalidHeaderFormat", + "inputs": [ + { + "name": "itemsLength", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "InvalidHeaderHeight", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidHeaderTimestamp", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidMixHash", + "inputs": [ + { + "name": "actualMixHash", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "InvalidNonce", + "inputs": [ + { + "name": "actualNonce", + "type": "bytes", + "internalType": "bytes" + } + ] + }, + { + "type": "error", + "name": "InvalidOmmersHash", + "inputs": [ + { + "name": "actualOmmersHash", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "InvalidPathLength", + "inputs": [ + { + "name": "expectedLength", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "actualLength", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "InvalidRevisionNumber", + "inputs": [ + { + "name": "providedRevisionNumber", + "type": "uint64", + "internalType": "uint64" + } + ] + }, + { + "type": "error", + "name": "InvalidValidatorAddress", + "inputs": [ + { + "name": "validator", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "InvalidValidatorAddressLength", + "inputs": [ + { + "name": "length", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "InvalidValueLength", + "inputs": [ + { + "name": "expectedLength", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "actualLength", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "UnsupportedMisbehaviour", + "inputs": [] + }, + { + "type": "error", + "name": "ValueExists", + "inputs": [ + { + "name": "actualValue", + "type": "bytes32", + "internalType": "bytes32" + } + ] + } +] diff --git a/ibc-solidity/abi/BesuQBFTLightClient.json b/ibc-solidity/abi/BesuQBFTLightClient.json new file mode 100644 index 000000000..b3b7b9852 --- /dev/null +++ b/ibc-solidity/abi/BesuQBFTLightClient.json @@ -0,0 +1,763 @@ +[ + { + "type": "constructor", + "inputs": [ + { + "name": "ibcRouter", + "type": "address", + "internalType": "address" + }, + { + "name": "initialTrustedHeight", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "initialTrustedTimestamp", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "initialTrustedStorageRoot", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "initialTrustedValidators", + "type": "address[]", + "internalType": "address[]" + }, + { + "name": "trustingPeriod", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "maxClockDrift", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "roleManager", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "DEFAULT_ADMIN_ROLE", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "PROOF_SUBMITTER_ROLE", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getClientState", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes", + "internalType": "bytes" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getConsensusState", + "inputs": [ + { + "name": "revisionHeight", + "type": "uint64", + "internalType": "uint64" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes", + "internalType": "bytes" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getRoleAdmin", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "grantRole", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "hasRole", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "misbehaviour", + "inputs": [ + { + "name": "", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "view" + }, + { + "type": "function", + "name": "renounceRole", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "callerConfirmation", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "revokeRole", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "supportsInterface", + "inputs": [ + { + "name": "interfaceId", + "type": "bytes4", + "internalType": "bytes4" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "updateClient", + "inputs": [ + { + "name": "updateMsg", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [ + { + "name": "", + "type": "uint8", + "internalType": "enum ILightClientMsgs.UpdateResult" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "verifyMembership", + "inputs": [ + { + "name": "msg_", + "type": "tuple", + "internalType": "struct ILightClientMsgs.MsgVerifyMembership", + "components": [ + { + "name": "proof", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "proofHeight", + "type": "tuple", + "internalType": "struct IICS02ClientMsgs.Height", + "components": [ + { + "name": "revisionNumber", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "revisionHeight", + "type": "uint64", + "internalType": "uint64" + } + ] + }, + { + "name": "path", + "type": "bytes[]", + "internalType": "bytes[]" + }, + { + "name": "value", + "type": "bytes", + "internalType": "bytes" + } + ] + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "verifyNonMembership", + "inputs": [ + { + "name": "msg_", + "type": "tuple", + "internalType": "struct ILightClientMsgs.MsgVerifyNonMembership", + "components": [ + { + "name": "proof", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "proofHeight", + "type": "tuple", + "internalType": "struct IICS02ClientMsgs.Height", + "components": [ + { + "name": "revisionNumber", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "revisionHeight", + "type": "uint64", + "internalType": "uint64" + } + ] + }, + { + "name": "path", + "type": "bytes[]", + "internalType": "bytes[]" + } + ] + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "event", + "name": "RoleAdminChanged", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "previousAdminRole", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "newAdminRole", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "RoleGranted", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "sender", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "RoleRevoked", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "sender", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "error", + "name": "AccessControlBadConfirmation", + "inputs": [] + }, + { + "type": "error", + "name": "AccessControlUnauthorizedAccount", + "inputs": [ + { + "name": "account", + "type": "address", + "internalType": "address" + }, + { + "name": "neededRole", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "ConflictingConsensusState", + "inputs": [ + { + "name": "revisionHeight", + "type": "uint64", + "internalType": "uint64" + } + ] + }, + { + "type": "error", + "name": "ConsensusStateExpired", + "inputs": [ + { + "name": "trustedTimestamp", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "currentTimestamp", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "trustingPeriod", + "type": "uint64", + "internalType": "uint64" + } + ] + }, + { + "type": "error", + "name": "ConsensusStateNotFound", + "inputs": [ + { + "name": "revisionHeight", + "type": "uint64", + "internalType": "uint64" + } + ] + }, + { + "type": "error", + "name": "DuplicateCommitSealSigner", + "inputs": [ + { + "name": "signer", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "DuplicateValidator", + "inputs": [ + { + "name": "validator", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "EmptyValidatorSet", + "inputs": [] + }, + { + "type": "error", + "name": "HeaderFromFuture", + "inputs": [ + { + "name": "currentTimestamp", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "headerTimestamp", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "maxClockDrift", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "InsufficientTrustedValidatorOverlap", + "inputs": [ + { + "name": "actual", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "required", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "InsufficientValidatorQuorum", + "inputs": [ + { + "name": "actual", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "required", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "InvalidCommitSeal", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidCommitmentValue", + "inputs": [ + { + "name": "expectedValue", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "actualValue", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "InvalidDifficulty", + "inputs": [ + { + "name": "actualDifficulty", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "InvalidECDSASignatureLength", + "inputs": [ + { + "name": "length", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "InvalidExtraDataFormat", + "inputs": [ + { + "name": "itemsLength", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "InvalidHeaderFormat", + "inputs": [ + { + "name": "itemsLength", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "InvalidHeaderHeight", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidHeaderTimestamp", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidMixHash", + "inputs": [ + { + "name": "actualMixHash", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "InvalidNonce", + "inputs": [ + { + "name": "actualNonce", + "type": "bytes", + "internalType": "bytes" + } + ] + }, + { + "type": "error", + "name": "InvalidOmmersHash", + "inputs": [ + { + "name": "actualOmmersHash", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "InvalidPathLength", + "inputs": [ + { + "name": "expectedLength", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "actualLength", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "InvalidRevisionNumber", + "inputs": [ + { + "name": "providedRevisionNumber", + "type": "uint64", + "internalType": "uint64" + } + ] + }, + { + "type": "error", + "name": "InvalidValidatorAddress", + "inputs": [ + { + "name": "validator", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "InvalidValidatorAddressLength", + "inputs": [ + { + "name": "length", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "InvalidValueLength", + "inputs": [ + { + "name": "expectedLength", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "actualLength", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "UnsupportedMisbehaviour", + "inputs": [] + }, + { + "type": "error", + "name": "ValueExists", + "inputs": [ + { + "name": "actualValue", + "type": "bytes32", + "internalType": "bytes32" + } + ] + } +] diff --git a/ibc-solidity/abi/bytecode/AttestationLightClient.json b/ibc-solidity/abi/bytecode/AttestationLightClient.json index 8039a88fc..25ced5389 100644 --- a/ibc-solidity/abi/bytecode/AttestationLightClient.json +++ b/ibc-solidity/abi/bytecode/AttestationLightClient.json @@ -1 +1 @@ -{"abi":[{"type":"constructor","inputs":[{"name":"attestorAddresses","type":"address[]","internalType":"address[]"},{"name":"minRequiredSigs","type":"uint8","internalType":"uint8"},{"name":"initialHeight","type":"uint64","internalType":"uint64"},{"name":"initialTimestampSeconds","type":"uint64","internalType":"uint64"},{"name":"roleManager","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"DEFAULT_ADMIN_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"PROOF_SUBMITTER_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"getAttestationSet","inputs":[],"outputs":[{"name":"attestorAddresses","type":"address[]","internalType":"address[]"},{"name":"minRequiredSigs","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"getClientState","inputs":[],"outputs":[{"name":"","type":"bytes","internalType":"bytes"}],"stateMutability":"view"},{"type":"function","name":"getConsensusTimestamp","inputs":[{"name":"revisionHeight","type":"uint64","internalType":"uint64"}],"outputs":[{"name":"","type":"uint64","internalType":"uint64"}],"stateMutability":"view"},{"type":"function","name":"getRoleAdmin","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"grantRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"hasRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"misbehaviour","inputs":[{"name":"","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"view"},{"type":"function","name":"renounceRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"callerConfirmation","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"revokeRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"updateClient","inputs":[{"name":"updateMsg","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"","type":"uint8","internalType":"enum ILightClientMsgs.UpdateResult"}],"stateMutability":"nonpayable"},{"type":"function","name":"verifyMembership","inputs":[{"name":"msg_","type":"tuple","internalType":"struct ILightClientMsgs.MsgVerifyMembership","components":[{"name":"proof","type":"bytes","internalType":"bytes"},{"name":"proofHeight","type":"tuple","internalType":"struct IICS02ClientMsgs.Height","components":[{"name":"revisionNumber","type":"uint64","internalType":"uint64"},{"name":"revisionHeight","type":"uint64","internalType":"uint64"}]},{"name":"path","type":"bytes[]","internalType":"bytes[]"},{"name":"value","type":"bytes","internalType":"bytes"}]}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"verifyNonMembership","inputs":[{"name":"msg_","type":"tuple","internalType":"struct ILightClientMsgs.MsgVerifyNonMembership","components":[{"name":"proof","type":"bytes","internalType":"bytes"},{"name":"proofHeight","type":"tuple","internalType":"struct IICS02ClientMsgs.Height","components":[{"name":"revisionNumber","type":"uint64","internalType":"uint64"},{"name":"revisionHeight","type":"uint64","internalType":"uint64"}]},{"name":"path","type":"bytes[]","internalType":"bytes[]"}]}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"event","name":"RoleAdminChanged","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"previousAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"newAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"error","name":"AccessControlBadConfirmation","inputs":[]},{"type":"error","name":"AccessControlUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"},{"name":"neededRole","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"BadQuorum","inputs":[{"name":"minRequired","type":"uint8","internalType":"uint8"},{"name":"attestationCount","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ConsensusTimestampNotFound","inputs":[{"name":"height","type":"uint64","internalType":"uint64"}]},{"type":"error","name":"DuplicateSigner","inputs":[{"name":"signer","type":"address","internalType":"address"}]},{"type":"error","name":"ECDSAInvalidSignature","inputs":[]},{"type":"error","name":"ECDSAInvalidSignatureLength","inputs":[{"name":"length","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ECDSAInvalidSignatureS","inputs":[{"name":"s","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"EmptyPackets","inputs":[]},{"type":"error","name":"EmptySignatures","inputs":[]},{"type":"error","name":"EmptyValue","inputs":[]},{"type":"error","name":"FeatureNotSupported","inputs":[]},{"type":"error","name":"FrozenClientState","inputs":[]},{"type":"error","name":"HeightMismatch","inputs":[{"name":"expected","type":"uint64","internalType":"uint64"},{"name":"provided","type":"uint64","internalType":"uint64"}]},{"type":"error","name":"InvalidPathLength","inputs":[{"name":"expectedLength","type":"uint256","internalType":"uint256"},{"name":"providedLength","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"InvalidSignatureLength","inputs":[{"name":"signature","type":"bytes","internalType":"bytes"}]},{"type":"error","name":"InvalidState","inputs":[{"name":"height","type":"uint64","internalType":"uint64"},{"name":"timestamp","type":"uint64","internalType":"uint64"}]},{"type":"error","name":"NoAttestors","inputs":[]},{"type":"error","name":"NotMember","inputs":[]},{"type":"error","name":"NotNonMember","inputs":[]},{"type":"error","name":"SignatureInvalid","inputs":[{"name":"signature","type":"bytes","internalType":"bytes"}]},{"type":"error","name":"ThresholdNotMet","inputs":[{"name":"validSigners","type":"uint256","internalType":"uint256"},{"name":"minRequired","type":"uint8","internalType":"uint8"}]},{"type":"error","name":"UnknownSigner","inputs":[{"name":"signer","type":"address","internalType":"address"}]}],"bytecode":{"object":"0x60806040523461032d57611f568038038061001981610349565b928339810160a08282031261032d5781516001600160401b03811161032d57820181601f8201121561032d578051916001600160401b0383116102c8578260051b916020610068818501610349565b8095815201906020829482010192831161032d57602001905b8282106103315750505060208301519260ff841680940361032d576100a860408201610382565b6100c060806100b960608501610382565b930161036e565b9284511561031e57851515806102f2575b855190156102dc575060405195608087016001600160401b038111888210176102c857604052858752602087019081526060604088019360018060401b03169788855201915f835286519060018060401b0382116102c8576801000000000000000082116102c85760015482600155808310610284575b5060015f5260205f205f5b838110610267575050505060ff90511669ff00000000000000000060025493610100600160481b03905160081b169251151560481b169260018060501b0319161717176002555f5b83518110156101fb5760018060a01b0360208260051b8601015116805f52600360205260ff60405f2054166101e957906001915f52600360205260405f208260ff198254161790550161019b565b637010e27960e11b5f5260045260245ffd5b505f84815260046020526040902080546001600160401b0319166001600160401b039092169190911790556001600160a01b03811661024e575061023d61048c565b505b6040516119a7908161050f8239f35b8061025b61026192610396565b5061040c565b5061023f565b82516001600160a01b031681830155602090920191600101610153565b60015f527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf69081019083015b8181106102bd5750610148565b5f81556001016102b0565b634e487b7160e01b5f52604160045260245ffd5b866365846b7f60e01b5f5260045260245260445ffd5b5084515f19870160ff811161030a5760ff16106100d1565b634e487b7160e01b5f52601160045260245ffd5b6343d0a89360e11b5f5260045ffd5b5f80fd5b6020809161033e8461036e565b815201910190610081565b6040519190601f01601f191682016001600160401b038111838210176102c857604052565b51906001600160a01b038216820361032d57565b51906001600160401b038216820361032d57565b6001600160a01b0381165f9081525f516020611f365f395f51905f52602052604090205460ff16610407576001600160a01b03165f8181525f516020611f365f395f51905f5260205260408120805460ff191660011790553391905f516020611eb65f395f51905f528180a4600190565b505f90565b6001600160a01b0381165f9081525f516020611ed65f395f51905f52602052604090205460ff16610407576001600160a01b03165f8181525f516020611ed65f395f51905f5260205260408120805460ff191660011790553391905f516020611f165f395f51905f52905f516020611eb65f395f51905f529080a4600190565b5f80525f516020611ed65f395f51905f526020525f516020611ef65f395f51905f525460ff1661050a575f8080525f516020611ed65f395f51905f526020525f516020611ef65f395f51905f52805460ff1916600117905533905f516020611f165f395f51905f525f516020611eb65f395f51905f528280a4600190565b5f9056fe6080806040526004361015610012575f80fd5b5f3560e01c90816301ffc9a7146106ab575080630bece356146105e8578063248a9ca3146105be5780632f2ff15d1461058f57806336568abe146105335780634d6d9ffb146104865780635832611b146104405780635972185a14610406578063682ed5f01461035157806391d1485414610308578063a217fddf146102ee578063a845a7f314610261578063d547741f1461022b578063ddba65371461015f5763ef913a4b146100c1575f80fd5b3461015b575f60031936011261015b576101576040516020808201526080604082015261014b816100f460c08201611228565b60ff600254818116606085015267ffffffffffffffff8160081c16608085015260481c16151560a0830152037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810183528261085e565b604051918291826107cd565b0390f35b5f80fd5b3461015b5761016d36610749565b505060ff60025460481c16610203575f80527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e06020527f6e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac475460ff16156101f6575b7fda81d7c2000000000000000000000000000000000000000000000000000000005f5260045ffd5b6101fe611277565b6101ce565b7f928b1233000000000000000000000000000000000000000000000000000000005f5260045ffd5b3461015b5761025f61023c3661079a565b9061025a610255825f525f602052600160405f20015490565b6112ff565b61175e565b005b3461015b575f60031936011261015b5760ff6002541660405161028e8161028781611228565b038261085e565b60405190604082019260408352815180945260206060840192015f945b8086106102c057505082935060208301520390f35b909260208060019273ffffffffffffffffffffffffffffffffffffffff8751168152019401950194906102ab565b3461015b575f60031936011261015b5760206040515f8152f35b3461015b576103163661079a565b905f525f60205273ffffffffffffffffffffffffffffffffffffffff60405f2091165f52602052602060ff60405f2054166040519015158152f35b3461015b57602060031936011261015b5760043567ffffffffffffffff811161015b5760a0600319823603011261015b5760ff60025460481c16610203575f80527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e060209081527f6e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac475490916103f19160ff16156103f9575b6004016110cb565b604051908152f35b610401611277565b6103e9565b3461015b575f60031936011261015b5760206040517fbd893629a699470e4ec82a5715bb4981fdaacc5d0a728bf5f55b801d8f4ef10b8152f35b3461015b57602060031936011261015b5760043567ffffffffffffffff811680910361015b575f526004602052602067ffffffffffffffff60405f205416604051908152f35b3461015b57602060031936011261015b5760043567ffffffffffffffff811161015b576080600319823603011261015b5760ff60025460481c16610203575f80527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e060209081527f6e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac475490916103f19160ff1615610526575b600401610ef5565b61052e611277565b61051e565b3461015b576105413661079a565b3373ffffffffffffffffffffffffffffffffffffffff8216036105675761025f9161175e565b7f6697b232000000000000000000000000000000000000000000000000000000005f5260045ffd5b3461015b5761025f6105a03661079a565b906105b9610255825f525f602052600160405f20015490565b61168c565b3461015b57602060031936011261015b5760206103f16004355f525f602052600160405f20015490565b3461015b576105f636610749565b60ff60025460481c16610203575f80527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e06020527f6e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac475461065e929060ff161561069e57610a3c565b6040516003821015610671576020918152f35b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b6106a6611277565b610a3c565b3461015b57602060031936011261015b57600435907fffffffff00000000000000000000000000000000000000000000000000000000821680920361015b57817f7965db0b000000000000000000000000000000000000000000000000000000006020931490811561071f575b5015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501483610718565b90602060031983011261015b5760043567ffffffffffffffff811161015b578260238201121561015b5780600401359267ffffffffffffffff841161015b576024848301011161015b576024019190565b600319604091011261015b576004359060243573ffffffffffffffffffffffffffffffffffffffff8116810361015b5790565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602060409481855280519182918282880152018686015e5f8582860101520116010190565b6040810190811067ffffffffffffffff82111761083157604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761083157604052565b92919267ffffffffffffffff821161083157604051916108e760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116018461085e565b82948184528183011161015b578281602093845f960137010152565b9080601f8301121561015b5781602061091e9335910161089f565b90565b67ffffffffffffffff81116108315760051b60200190565b60208183031261015b5780359067ffffffffffffffff821161015b57019060408282031261015b576040519161096e83610815565b803567ffffffffffffffff811161015b578261098b918301610903565b835260208101359067ffffffffffffffff821161015b57019080601f8301121561015b5781356109ba81610921565b926109c8604051948561085e565b81845260208085019260051b8201019183831161015b5760208201905b8382106109f9575050505050602082015290565b813567ffffffffffffffff811161015b57602091610a1c87848094880101610903565b8152019101906109e5565b519067ffffffffffffffff8216820361015b57565b610a4891810190610939565b60205f818351604051918183925191829101835e8101838152039060025afa15610c915760205f8051604051838101917f01000000000000000000000000000000000000000000000000000000000000008352602182015260218152610aaf60418261085e565b604051918291518091835e8101838152039060025afa15610c9157610ada5f516020830151906113eb565b5160408180518101031261015b57604051610af481610815565b610b0f6040610b0560208501610a27565b9384845201610a27565b67ffffffffffffffff60208301938285521680151580610c7e575b15610c4457505067ffffffffffffffff8151165f52600460205267ffffffffffffffff60405f20541680610bf3575067ffffffffffffffff9051918183169260025490838260081c168511610bb6575b50505116905f52600460205260405f20907fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008254161790555f90565b68ffffffffffffffff007fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff9160081b169116176002555f80610b7a565b9167ffffffffffffffff9150511603610c0b57600290565b69010000000000000000007fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff6002541617600255600190565b67ffffffffffffffff92507fdcbc5460000000000000000000000000000000000000000000000000000000005f526004521660245260445ffd5b5067ffffffffffffffff82161515610b2a565b6040513d5f823e3d90fd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561015b570180359067ffffffffffffffff821161015b57602001918160051b3603831361015b57565b3567ffffffffffffffff8116810361015b5790565b15610d0d5750565b67ffffffffffffffff907ff7caaa5c000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561015b570180359067ffffffffffffffff821161015b5760200191813603831361015b57565b60208183031261015b5780519067ffffffffffffffff821161015b57019060408282031261015b5760405191610dc983610815565b610dd281610a27565b835260208101519067ffffffffffffffff821161015b570181601f8201121561015b57805190610e0182610921565b92610e0f604051948561085e565b82845260208085019360061b8301019181831161015b57602001925b828410610e3e5750505050602082015290565b60408483031261015b5760206040918251610e5881610815565b865181528287015183820152815201930192610e2b565b15610e78575050565b9067ffffffffffffffff80927fc7441689000000000000000000000000000000000000000000000000000000005f52166004521660245260445ffd5b8051821015610ec85760209160051b010190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b6060810190610f048282610c9c565b90506001610f128484610c9c565b9290500361109b5750610fb8610f2a60408301610cf0565b9267ffffffffffffffff841692835f526004602052610fb367ffffffffffffffff60405f20541694610f5e87871515610d05565b610f9e610f76610f6e8580610d43565b810190610939565b610f8e610f838251611365565b6020830151906113eb565b5160208082518301019101610d94565b9667ffffffffffffffff885116918214610e6f565b610c9c565b15610ec857610fd3610fcc82602093610d43565b369161089f565b818151910120920180515115611073575f5b8151805182101561104b57610ffb828692610eb4565b51511461100a57600101610fe5565b60209293506110199151610eb4565b5101516110235790565b7f9a960b4f000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f291fc442000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f1e6c84da000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f88b3170e000000000000000000000000000000000000000000000000000000005f52600160045260245260445ffd5b608081016110d98183610d43565b9050156112005760608201906110ef8284610c9c565b905060016110fd8486610c9c565b9290500361109b575061111260408401610cf0565b9061117467ffffffffffffffff831693845f52600460205261116e67ffffffffffffffff60405f2054169561114986881515610d05565b611159610f76610f6e8a80610d43565b9567ffffffffffffffff875116918214610e6f565b85610c9c565b15610ec85760209161118c610fcc8361119894610d43565b83815191012095610d43565b908092918101031261015b576020903591019081515115611073575f5b8251805182101561104b576111cb828792610eb4565b515114806111e8575b6111e0576001016111b5565b505050905090565b508160206111f7838651610eb4565b510151146111d4565b7f1208b21b000000000000000000000000000000000000000000000000000000005f5260045ffd5b602060015491828152019060015f5260205f20905f5b81811061124b5750505090565b825473ffffffffffffffffffffffffffffffffffffffff1684526020909301926001928301920161123e565b335f9081527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e0602052604090205460ff16156112af57565b7fe2517d3f000000000000000000000000000000000000000000000000000000005f52336004527fbd893629a699470e4ec82a5715bb4981fdaacc5d0a728bf5f55b801d8f4ef10b60245260445ffd5b805f525f60205260405f2073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f205416156113365750565b7fe2517d3f000000000000000000000000000000000000000000000000000000005f523360045260245260445ffd5b5f60208092604051918183925191829101835e8101838152039060025afa15610c915760205f8051604051838101917f020000000000000000000000000000000000000000000000000000000000000083526021820152602181526113cb60418261085e565b604051918291518091835e8101838152039060025afa15610c91575f5190565b91909182511561166457825160ff60025416907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82019060ff82116116375760ff8651921610156116095750508251927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061147e61146886610921565b95611476604051978861085e565b808752610921565b013660208601375f5b81518110156116025761149a8183610eb4565b5160418151036115cc5773ffffffffffffffffffffffffffffffffffffffff6114cf6114c68387611826565b90929192611860565b169081156115925750805f52600360205260ff60405f20541615611567575f5b82811061150c5750906001916115058288610eb4565b5201611487565b8173ffffffffffffffffffffffffffffffffffffffff61152c838a610eb4565b51161461153b576001016114ef565b507fe021c4f2000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b7fd7e8a2c2000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b6115c8906040519182917f9e3c1b3d000000000000000000000000000000000000000000000000000000008352600483016107cd565b0390fd5b6115c8906040519182917f2ee17a3d000000000000000000000000000000000000000000000000000000008352600483016107cd565b5050509050565b7f378b0805000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b7f301b38b6000000000000000000000000000000000000000000000000000000005f5260045ffd5b805f525f60205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260ff60405f205416155f1461175857805f525f60205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260405f2060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905573ffffffffffffffffffffffffffffffffffffffff339216907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d5f80a4600190565b50505f90565b805f525f60205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260ff60405f2054165f1461175857805f525f60205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260405f207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00815416905573ffffffffffffffffffffffffffffffffffffffff339216907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b5f80a4600190565b81519190604183036118565761184f9250602082015190606060408401519301515f1a9061190b565b9192909190565b50505f9160029190565b60048110156106715780611872575050565b600181036118a2577ff645eedf000000000000000000000000000000000000000000000000000000005f5260045ffd5b600281036118d657507ffce698f7000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b6003146118e05750565b7fd78bce0c000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841161198f579160209360809260ff5f9560405194855216868401526040830152606082015282805260015afa15610c91575f5173ffffffffffffffffffffffffffffffffffffffff81161561198557905f905f90565b505f906001905f90565b5050505f916003919056fea164736f6c634300081c000a2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e06e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac47bd893629a699470e4ec82a5715bb4981fdaacc5d0a728bf5f55b801d8f4ef10bad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5","sourceMap":"815:11749:29:-:0;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;-1:-1:-1;;;;;815:11749:29;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;815:11749:29;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;2648:28;815:11749;;2723:19;;;:69;;;815:11749;;;;;;;-1:-1:-1;815:11749:29;;;;;;-1:-1:-1;;;;;815:11749:29;;;;;;;;;;;;;;2893:217;;815:11749;;;;;2893:217;;815:11749;;;;;;;;;;;2893:217;815:11749;-1:-1:-1;815:11749:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;815:11749:29;;-1:-1:-1;815:11749:29;-1:-1:-1;815:11749:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;3171:3:29;815:11749;;3141:28;;;;;815:11749;;;;;;;;;;;;;;;-1:-1:-1;815:11749:29;3251:11;815:11749;;;;-1:-1:-1;815:11749:29;;;;;;;;-1:-1:-1;815:11749:29;3251:11;815:11749;;;-1:-1:-1;815:11749:29;;;;;;;;;;;3126:13;;815:11749;;;;-1:-1:-1;815:11749:29;;;;-1:-1:-1;815:11749:29;3141:28;-1:-1:-1;;815:11749:29;;;3372:27;815:11749;;;;;;;-1:-1:-1;;;;;;815:11749:29;-1:-1:-1;;;;;815:11749:29;;;;;;;;;-1:-1:-1;;;;;815:11749:29;;;;3496:44;;;:::i;:::-;;3451:249;815:11749;;;;;;;;;3451:249;3587:43;;3644:45;3587:43;;:::i;:::-;;3644:45;:::i;:::-;;3451:249;;815:11749;;;-1:-1:-1;;;;;815:11749:29;;;;;;;;;;;;;;;;-1:-1:-1;815:11749:29;;;;;;;;;;;;;;;;;;-1:-1:-1;815:11749:29;;;;;;;;;;-1:-1:-1;815:11749:29;;;;;-1:-1:-1;815:11749:29;;;;;;-1:-1:-1;815:11749:29;;;;;;-1:-1:-1;815:11749:29;2723:69;-1:-1:-1;815:11749:29;;-1:-1:-1;;815:11749:29;;;;;;;;;-1:-1:-1;2723:69:29;;815:11749;;;;-1:-1:-1;815:11749:29;;;;;-1:-1:-1;815:11749:29;;;;;-1:-1:-1;815:11749:29;;-1:-1:-1;815:11749:29;;-1:-1:-1;815:11749:29;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;;815:11749:29;;;-1:-1:-1;;;;;815:11749:29;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;;;815:11749:29;;;;;;:::o;:::-;;;-1:-1:-1;;;;;815:11749:29;;;;;;:::o;6155:316:84:-;-1:-1:-1;;;;;815:11749:29;;2675:1;815:11749;;;-1:-1:-1;;;;;;;;;;;815:11749:29;;;;;;;;;;-1:-1:-1;;;;;815:11749:29;2675:1;815:11749;;;-1:-1:-1;;;;;;;;;;;815:11749:29;;;;;;;-1:-1:-1;;815:11749:29;;;;;735:10:112;;815:11749:29;-1:-1:-1;;;;;;;;;;;2675:1:29;;6346:40:84;6323:4;6400:11;:::o;6248:217::-;6442:12;2675:1:29;6442:12:84;:::o;6155:316::-;-1:-1:-1;;;;;815:11749:29;;;;;;-1:-1:-1;;;;;;;;;;;815:11749:29;;;;;;;;;;-1:-1:-1;;;;;815:11749:29;;;;;-1:-1:-1;;;;;;;;;;;815:11749:29;;;;;;;-1:-1:-1;;815:11749:29;;;;;735:10:112;;815:11749:29;-1:-1:-1;;;;;;;;;;;1507:33:29;-1:-1:-1;;;;;;;;;;;6346:40:84;815:11749:29;6346:40:84;6323:4;6400:11;:::o;6155:316::-;815:11749:29;;;-1:-1:-1;;;;;;;;;;;815:11749:29;;-1:-1:-1;;;;;;;;;;;815:11749:29;;;;;;;;;-1:-1:-1;;;;;;;;;;;815:11749:29;;-1:-1:-1;;;;;;;;;;;815:11749:29;;-1:-1:-1;;815:11749:29;6323:4:84;815:11749:29;;;735:10:112;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;815:11749:29;;6346:40:84;6323:4;6400:11;:::o;6248:217::-;815:11749:29;6442:12:84;:::o","linkReferences":{}},"deployedBytecode":{"object":"0x6080806040526004361015610012575f80fd5b5f3560e01c90816301ffc9a7146106ab575080630bece356146105e8578063248a9ca3146105be5780632f2ff15d1461058f57806336568abe146105335780634d6d9ffb146104865780635832611b146104405780635972185a14610406578063682ed5f01461035157806391d1485414610308578063a217fddf146102ee578063a845a7f314610261578063d547741f1461022b578063ddba65371461015f5763ef913a4b146100c1575f80fd5b3461015b575f60031936011261015b576101576040516020808201526080604082015261014b816100f460c08201611228565b60ff600254818116606085015267ffffffffffffffff8160081c16608085015260481c16151560a0830152037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810183528261085e565b604051918291826107cd565b0390f35b5f80fd5b3461015b5761016d36610749565b505060ff60025460481c16610203575f80527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e06020527f6e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac475460ff16156101f6575b7fda81d7c2000000000000000000000000000000000000000000000000000000005f5260045ffd5b6101fe611277565b6101ce565b7f928b1233000000000000000000000000000000000000000000000000000000005f5260045ffd5b3461015b5761025f61023c3661079a565b9061025a610255825f525f602052600160405f20015490565b6112ff565b61175e565b005b3461015b575f60031936011261015b5760ff6002541660405161028e8161028781611228565b038261085e565b60405190604082019260408352815180945260206060840192015f945b8086106102c057505082935060208301520390f35b909260208060019273ffffffffffffffffffffffffffffffffffffffff8751168152019401950194906102ab565b3461015b575f60031936011261015b5760206040515f8152f35b3461015b576103163661079a565b905f525f60205273ffffffffffffffffffffffffffffffffffffffff60405f2091165f52602052602060ff60405f2054166040519015158152f35b3461015b57602060031936011261015b5760043567ffffffffffffffff811161015b5760a0600319823603011261015b5760ff60025460481c16610203575f80527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e060209081527f6e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac475490916103f19160ff16156103f9575b6004016110cb565b604051908152f35b610401611277565b6103e9565b3461015b575f60031936011261015b5760206040517fbd893629a699470e4ec82a5715bb4981fdaacc5d0a728bf5f55b801d8f4ef10b8152f35b3461015b57602060031936011261015b5760043567ffffffffffffffff811680910361015b575f526004602052602067ffffffffffffffff60405f205416604051908152f35b3461015b57602060031936011261015b5760043567ffffffffffffffff811161015b576080600319823603011261015b5760ff60025460481c16610203575f80527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e060209081527f6e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac475490916103f19160ff1615610526575b600401610ef5565b61052e611277565b61051e565b3461015b576105413661079a565b3373ffffffffffffffffffffffffffffffffffffffff8216036105675761025f9161175e565b7f6697b232000000000000000000000000000000000000000000000000000000005f5260045ffd5b3461015b5761025f6105a03661079a565b906105b9610255825f525f602052600160405f20015490565b61168c565b3461015b57602060031936011261015b5760206103f16004355f525f602052600160405f20015490565b3461015b576105f636610749565b60ff60025460481c16610203575f80527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e06020527f6e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac475461065e929060ff161561069e57610a3c565b6040516003821015610671576020918152f35b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b6106a6611277565b610a3c565b3461015b57602060031936011261015b57600435907fffffffff00000000000000000000000000000000000000000000000000000000821680920361015b57817f7965db0b000000000000000000000000000000000000000000000000000000006020931490811561071f575b5015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501483610718565b90602060031983011261015b5760043567ffffffffffffffff811161015b578260238201121561015b5780600401359267ffffffffffffffff841161015b576024848301011161015b576024019190565b600319604091011261015b576004359060243573ffffffffffffffffffffffffffffffffffffffff8116810361015b5790565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602060409481855280519182918282880152018686015e5f8582860101520116010190565b6040810190811067ffffffffffffffff82111761083157604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761083157604052565b92919267ffffffffffffffff821161083157604051916108e760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116018461085e565b82948184528183011161015b578281602093845f960137010152565b9080601f8301121561015b5781602061091e9335910161089f565b90565b67ffffffffffffffff81116108315760051b60200190565b60208183031261015b5780359067ffffffffffffffff821161015b57019060408282031261015b576040519161096e83610815565b803567ffffffffffffffff811161015b578261098b918301610903565b835260208101359067ffffffffffffffff821161015b57019080601f8301121561015b5781356109ba81610921565b926109c8604051948561085e565b81845260208085019260051b8201019183831161015b5760208201905b8382106109f9575050505050602082015290565b813567ffffffffffffffff811161015b57602091610a1c87848094880101610903565b8152019101906109e5565b519067ffffffffffffffff8216820361015b57565b610a4891810190610939565b60205f818351604051918183925191829101835e8101838152039060025afa15610c915760205f8051604051838101917f01000000000000000000000000000000000000000000000000000000000000008352602182015260218152610aaf60418261085e565b604051918291518091835e8101838152039060025afa15610c9157610ada5f516020830151906113eb565b5160408180518101031261015b57604051610af481610815565b610b0f6040610b0560208501610a27565b9384845201610a27565b67ffffffffffffffff60208301938285521680151580610c7e575b15610c4457505067ffffffffffffffff8151165f52600460205267ffffffffffffffff60405f20541680610bf3575067ffffffffffffffff9051918183169260025490838260081c168511610bb6575b50505116905f52600460205260405f20907fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008254161790555f90565b68ffffffffffffffff007fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff9160081b169116176002555f80610b7a565b9167ffffffffffffffff9150511603610c0b57600290565b69010000000000000000007fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff6002541617600255600190565b67ffffffffffffffff92507fdcbc5460000000000000000000000000000000000000000000000000000000005f526004521660245260445ffd5b5067ffffffffffffffff82161515610b2a565b6040513d5f823e3d90fd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561015b570180359067ffffffffffffffff821161015b57602001918160051b3603831361015b57565b3567ffffffffffffffff8116810361015b5790565b15610d0d5750565b67ffffffffffffffff907ff7caaa5c000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561015b570180359067ffffffffffffffff821161015b5760200191813603831361015b57565b60208183031261015b5780519067ffffffffffffffff821161015b57019060408282031261015b5760405191610dc983610815565b610dd281610a27565b835260208101519067ffffffffffffffff821161015b570181601f8201121561015b57805190610e0182610921565b92610e0f604051948561085e565b82845260208085019360061b8301019181831161015b57602001925b828410610e3e5750505050602082015290565b60408483031261015b5760206040918251610e5881610815565b865181528287015183820152815201930192610e2b565b15610e78575050565b9067ffffffffffffffff80927fc7441689000000000000000000000000000000000000000000000000000000005f52166004521660245260445ffd5b8051821015610ec85760209160051b010190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b6060810190610f048282610c9c565b90506001610f128484610c9c565b9290500361109b5750610fb8610f2a60408301610cf0565b9267ffffffffffffffff841692835f526004602052610fb367ffffffffffffffff60405f20541694610f5e87871515610d05565b610f9e610f76610f6e8580610d43565b810190610939565b610f8e610f838251611365565b6020830151906113eb565b5160208082518301019101610d94565b9667ffffffffffffffff885116918214610e6f565b610c9c565b15610ec857610fd3610fcc82602093610d43565b369161089f565b818151910120920180515115611073575f5b8151805182101561104b57610ffb828692610eb4565b51511461100a57600101610fe5565b60209293506110199151610eb4565b5101516110235790565b7f9a960b4f000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f291fc442000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f1e6c84da000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f88b3170e000000000000000000000000000000000000000000000000000000005f52600160045260245260445ffd5b608081016110d98183610d43565b9050156112005760608201906110ef8284610c9c565b905060016110fd8486610c9c565b9290500361109b575061111260408401610cf0565b9061117467ffffffffffffffff831693845f52600460205261116e67ffffffffffffffff60405f2054169561114986881515610d05565b611159610f76610f6e8a80610d43565b9567ffffffffffffffff875116918214610e6f565b85610c9c565b15610ec85760209161118c610fcc8361119894610d43565b83815191012095610d43565b908092918101031261015b576020903591019081515115611073575f5b8251805182101561104b576111cb828792610eb4565b515114806111e8575b6111e0576001016111b5565b505050905090565b508160206111f7838651610eb4565b510151146111d4565b7f1208b21b000000000000000000000000000000000000000000000000000000005f5260045ffd5b602060015491828152019060015f5260205f20905f5b81811061124b5750505090565b825473ffffffffffffffffffffffffffffffffffffffff1684526020909301926001928301920161123e565b335f9081527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e0602052604090205460ff16156112af57565b7fe2517d3f000000000000000000000000000000000000000000000000000000005f52336004527fbd893629a699470e4ec82a5715bb4981fdaacc5d0a728bf5f55b801d8f4ef10b60245260445ffd5b805f525f60205260405f2073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f205416156113365750565b7fe2517d3f000000000000000000000000000000000000000000000000000000005f523360045260245260445ffd5b5f60208092604051918183925191829101835e8101838152039060025afa15610c915760205f8051604051838101917f020000000000000000000000000000000000000000000000000000000000000083526021820152602181526113cb60418261085e565b604051918291518091835e8101838152039060025afa15610c91575f5190565b91909182511561166457825160ff60025416907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82019060ff82116116375760ff8651921610156116095750508251927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061147e61146886610921565b95611476604051978861085e565b808752610921565b013660208601375f5b81518110156116025761149a8183610eb4565b5160418151036115cc5773ffffffffffffffffffffffffffffffffffffffff6114cf6114c68387611826565b90929192611860565b169081156115925750805f52600360205260ff60405f20541615611567575f5b82811061150c5750906001916115058288610eb4565b5201611487565b8173ffffffffffffffffffffffffffffffffffffffff61152c838a610eb4565b51161461153b576001016114ef565b507fe021c4f2000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b7fd7e8a2c2000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b6115c8906040519182917f9e3c1b3d000000000000000000000000000000000000000000000000000000008352600483016107cd565b0390fd5b6115c8906040519182917f2ee17a3d000000000000000000000000000000000000000000000000000000008352600483016107cd565b5050509050565b7f378b0805000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b7f301b38b6000000000000000000000000000000000000000000000000000000005f5260045ffd5b805f525f60205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260ff60405f205416155f1461175857805f525f60205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260405f2060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905573ffffffffffffffffffffffffffffffffffffffff339216907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d5f80a4600190565b50505f90565b805f525f60205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260ff60405f2054165f1461175857805f525f60205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260405f207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00815416905573ffffffffffffffffffffffffffffffffffffffff339216907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b5f80a4600190565b81519190604183036118565761184f9250602082015190606060408401519301515f1a9061190b565b9192909190565b50505f9160029190565b60048110156106715780611872575050565b600181036118a2577ff645eedf000000000000000000000000000000000000000000000000000000005f5260045ffd5b600281036118d657507ffce698f7000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b6003146118e05750565b7fd78bce0c000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841161198f579160209360809260ff5f9560405194855216868401526040830152606082015282805260015afa15610c91575f5173ffffffffffffffffffffffffffffffffffffffff81161561198557905f905f90565b505f906001905f90565b5050505f916003919056fea164736f6c634300081c000a","sourceMap":"815:11749:29:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;815:11749:29;;;;;;;;3825:23;;;;815:11749;;;;;;3825:23;815:11749;;;;;;:::i;:::-;;;;;;;;;;;;1787:4;;;815:11749;;;;;;;;;;;;;;3825:23;;;;;;;;:::i;:::-;815:11749;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;;;;12225:20;815:11749;;;;;;;;;;;;;;;;12444:42;12440:105;;815:11749;9710:21;815:11749;9710:21;815:11749;;9710:21;12440:105;12513:20;;:::i;:::-;12440:105;;815:11749;;;;;;;;;;;4723:26:84;815:11749:29;;;:::i;:::-;4693:18:84;2484:4;4693:18;;3877:6;815:11749:29;3877:6:84;815:11749:29;;3877:22:84;815:11749:29;3877:6:84;815:11749:29;3877:22:84;815:11749:29;3786:120:84;;4693:18;2484:4;:::i;:::-;4723:26;:::i;:::-;815:11749:29;;;;;;-1:-1:-1;;815:11749:29;;;;;;4065:27;815:11749;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4034:11;815:11749;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;815:11749:29;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;2930:29:84;815:11749:29;-1:-1:-1;815:11749:29;;;;;;-1:-1:-1;815:11749:29;;;;;;;;;;;;;;;;-1:-1:-1;;815:11749:29;;;;;;;;;;;;;-1:-1:-1;;815:11749:29;;;;;;;;12225:20;815:11749;;;;;;;;;;;;;;;;;;5841:1853;;815:11749;;12444:42;12440:105;;815:11749;;;5841:1853;:::i;:::-;815:11749;;;;;;12440:105;12513:20;;:::i;:::-;12440:105;;815:11749;;;;;-1:-1:-1;;815:11749:29;;;;;;;;1507:33;815:11749;;;;;;;;-1:-1:-1;;815:11749:29;;;;;;;;;;;;;;;;1787:4;815:11749;;1787:4;815:11749;;;;1787:4;;815:11749;;;;;;;;;;;;-1:-1:-1;;815:11749:29;;;;;;;;;;;;;-1:-1:-1;;815:11749:29;;;;;;;;12225:20;815:11749;;;;;;;;;;;;;;;;;;7733:1799;;815:11749;;12444:42;12440:105;;815:11749;;;7733:1799;:::i;12440:105::-;12513:20;;:::i;:::-;12440:105;;815:11749;;;;;;;:::i;:::-;735:10:112;815:11749:29;;;5397:34:84;5393:102;;5505:37;;;:::i;5393:102::-;5454:30;815:11749:29;5454:30:84;815:11749:29;;5454:30:84;815:11749:29;;;;4306:25:84;815:11749:29;;;:::i;:::-;4276:18:84;2484:4;4276:18;;3877:6;815:11749:29;3877:6:84;815:11749:29;;3877:22:84;815:11749:29;3877:6:84;815:11749:29;3877:22:84;815:11749:29;3786:120:84;;2484:4;4306:25;:::i;815:11749:29:-;;;;;-1:-1:-1;;815:11749:29;;;;;;;;;3877:6:84;815:11749:29;3877:6:84;815:11749:29;;3877:22:84;815:11749:29;3877:6:84;815:11749:29;3877:22:84;815:11749:29;3786:120:84;;815:11749:29;;;;;;;:::i;:::-;;12225:20;815:11749;;;;;;;;;;;;;;4341:1461;;815:11749;;;12444:42;12440:105;;4341:1461;:::i;:::-;815:11749;;;;;;;;;;;;;;;;;;;;;;;12440:105;12513:20;;:::i;:::-;4341:1461;:::i;815:11749::-;;;;;-1:-1:-1;;815:11749:29;;;;;;;;;;;;;;;;2649:47:84;2664:32;815:11749:29;2649:47:84;;:87;;;;;815:11749:29;;;;;;;2649:87:84;844:25:124;829:40;;;2649:87:84;;;815:11749:29;;;-1:-1:-1;;815:11749:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;-1:-1:-1;;815:11749:29;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;:::o;:::-;;-1:-1:-1;815:11749:29;;;;;-1:-1:-1;815:11749:29;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;-1:-1:-1;815:11749:29;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;1787:4;;815:11749;;;;;;;;1787:4::o;4341:1461::-;4562:58;4341:1461;4562:58;;;;:::i;:::-;815:11749;-1:-1:-1;4668:21:29;;;815:11749;;;;;;;;;;;;;;;;;;10125:12;;;;;;;;815:11749;-1:-1:-1;10125:12:29;;815:11749;;10099:39;;;815:11749;;;;;;;;;10099:39;;;;;;:::i;:::-;815:11749;;;;;;;;;;;;;;;10092:47;;10125:12;10092:47;;;;;4759:16;-1:-1:-1;10092:47:29;815:11749;4759:16;;;;;:::i;:::-;4859:21;815:11749;;;;4848:70;;1787:4;;;;815:11749;;;;;:::i;:::-;1787:4;815:11749;1787:4;815:11749;4848:70;;1787:4;:::i;:::-;;;;;;;:::i;:::-;815:11749;;1787:4;;;;;;815:11749;4937:16;;;:39;;;4341:1461;1787:4;;;;;815:11749;1787:4;;815:11749;-1:-1:-1;1787:4:29;5227:27;815:11749;1787:4;815:11749;;-1:-1:-1;1787:4:29;;815:11749;5282:22;5278:276;;1787:4;815:11749;1787:4;;815:11749;;;;1787:4;10125:12;1787:4;;;;;;815:11749;5568:39;;5564:109;;4341:1461;1787:4;;;815:11749;1787:4;-1:-1:-1;1787:4:29;5227:27;815:11749;1787:4;815:11749;-1:-1:-1;1787:4:29;;;;;;;;;-1:-1:-1;4341:1461:29;:::o;5564:109::-;1787:4;;;;;;;;;10125:12;1787:4;5564:109;;;;5278:276;1787:4;815:11749;1787:4;;;815:11749;5324:36;5320:169;;10125:12;5502:41;:::o;5320:169::-;1787:4;;10125:12;1787:4;;;10125:12;1787:4;;5425:49;:::o;1787:4::-;815:11749;1787:4;;;-1:-1:-1;1787:4:29;;815:11749;;1787:4;815:11749;1787:4;-1:-1:-1;1787:4:29;4937:39;815:11749;;;;4957:19;;4937:39;;10092:47;815:11749;;;-1:-1:-1;815:11749:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;:::o;:::-;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;1910:4::-;;;;;;;;;;;;;;;;;;;;;;;;;;815:11749;;;;;:::i;:::-;1787:4;;;:::i;:::-;1910;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;815:11749;;1910:4;815:11749;;;;:::i;:::-;1910:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;815:11749;;;;;;:::i;:::-;1910:4;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;815:11749;1910:4;;;;;815:11749;1910:4;815:11749;;1787:4;815:11749;1787:4;1910;;;815:11749;;1910:4;;;;;;;;;;;;:::o;:::-;;;;;;;;;;7733:1799;7940:9;;;;;;;;:::i;:::-;7984;;7960:1;7984:9;;;;:::i;:::-;7940:21;;;;815:11749;;8104:31;9118:9;8104:31;;;;;:::i;:::-;815:11749;;;;1787:4;;-1:-1:-1;1787:4:29;8157:27;8104:16;1787:4;8893:103;815:11749;8104:31;-1:-1:-1;1787:4:29;;815:11749;8215:7;8207:57;8215:7;;;;8207:57;:::i;:::-;8739:71;8324:59;8335:10;;;;:::i;:::-;8324:59;;;;:::i;:::-;8522:16;8410:67;8430:21;;8410:67;:::i;:::-;8104:16;8522;;;;;:::i;:::-;8750:21;8104:16;815:11749;;;8739:71;;;;;;:::i;:::-;1787:4;815:11749;1787:4;;815:11749;8901:39;;;8893:103;:::i;:::-;9118:9;:::i;:::-;1910:4;;;;;;8104:16;1910:4;;:::i;:::-;;;;:::i;:::-;815:11749;;;;;9108:23;9149:25;;;;815:11749;9149:36;1910:4;;-1:-1:-1;9270:3:29;9236:25;;815:11749;;9232:36;;;;;9293:28;;;;;:::i;:::-;;1910:4;9293:45;9289:198;;7960:1;1910:4;9217:13;;9289:198;8104:16;9366:25;;;:28;:25;;:28;:::i;:::-;;:39;1910:4;;;9454:18;:::o;1910:4::-;;-1:-1:-1;1910:4:29;8157:27;-1:-1:-1;1910:4:29;9232:36;9514:11;-1:-1:-1;9514:11:29;8157:27;-1:-1:-1;9514:11:29;1910:4;;-1:-1:-1;1910:4:29;8157:27;-1:-1:-1;1910:4:29;815:11749;;;;7960:1;815:11749;;;;;;;5841:1853;6042:10;;;;;;;:::i;:::-;:22;;;815:11749;;6097:9;;;;;;;;:::i;:::-;6141;;6117:1;6141:9;;;;:::i;:::-;6097:21;;;;815:11749;;6261:31;;;;;;:::i;:::-;815:11749;7265:9;815:11749;;;1787:4;;6063:1;1787:4;6314:27;6261:16;1787:4;7050:103;815:11749;6261:31;6063:1;1787:4;;815:11749;6372:7;6364:57;6372:7;;;;6364:57;:::i;:::-;6896:71;6481:59;6492:10;;;;:::i;6896:71::-;1787:4;815:11749;1787:4;;815:11749;7058:39;;;7050:103;:::i;:::-;7265:9;;:::i;:::-;1910:4;;;6261:16;1910:4;;;;7315:10;1910:4;;:::i;:::-;815:11749;;;;;7255:23;7315:10;;:::i;:::-;7304:33;;;;;;815:11749;;;;6261:16;815:11749;;7355:25;;;;;815:11749;7355:36;1910:4;;6063:1;7476:3;7442:25;;815:11749;;7438:36;;;;;7499:28;;;;;:::i;:::-;;1910:4;7499:45;:97;;;7476:3;7495:154;;6117:1;1910:4;7423:13;;7495:154;7616:18;;;;;;:::o;7499:97::-;7548:25;;6261:16;7548:28;:25;;;:28;:::i;:::-;;:39;1910:4;7548:48;7499:97;;815:11749;;6063:1;815:11749;;6063:1;815:11749;;;4034:11;815:11749;;;;;;;4034:11;-1:-1:-1;815:11749:29;;-1:-1:-1;815:11749:29;;-1:-1:-1;815:11749:29;;;;;;;;;;:::o;:::-;;;;;;;;;;;;4034:11;815:11749;;;;;;;3175:103:84;735:10:112;2930:6:84;815:11749:29;;;;;;;;;;;;3495:23:84;3491:108;;3175:103::o;3491:108::-;3541:47;2930:6;3541:47;735:10:112;3541:47:84;815:11749:29;1507:33;815:11749;;;2930:6:84;3541:47;3175:103;815:11749:29;2930:6:84;815:11749:29;2930:6:84;815:11749:29;;;2930:6:84;815:11749:29;;735:10:112;815:11749:29;-1:-1:-1;815:11749:29;;;;;-1:-1:-1;815:11749:29;;;3495:23:84;3491:108;;3175:103;:::o;3491:108::-;3541:47;2930:6;3541:47;735:10:112;3541:47:84;815:11749:29;;;;2930:6:84;3541:47;9980:166:29;-1:-1:-1;815:11749:29;9980:166;;815:11749;;;;;;;;;;;;;;;;;;10125:12;;;;;;;;815:11749;-1:-1:-1;10125:12:29;;815:11749;;10099:39;;;815:11749;;;;;;;;;10099:39;;;;;;:::i;:::-;815:11749;;;;;;;;;;;;;;;10092:47;;10125:12;10092:47;;;;;-1:-1:-1;10092:47:29;9980:166;:::o;10562:773::-;;;;815:11749;;10672:21;815:11749;;;;;10765:27;815:11749;;;;;;;;;;;;;;;;;-1:-1:-1;815:11749:29;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;10692:1;11003:3;815:11749;;10980:21;;;;;11041:13;;;;:::i;:::-;;1660:2;815:11749;;11811:42;1660:2;;815:11749;5503:8:122;5447:27;;;;:::i;:::-;5503:8;;;;;:::i;:::-;815:11749:29;11970:23;;;1660:2;;815:11749;;10692:1;815:11749;12041:11;815:11749;;;;10692:1;815:11749;;;1660:2;;;10692:1;11184:5;;;;;;11299:19;;10765:11;11299:19;;;;;:::i;:::-;815:11749;1910:4;10965:13;;11191:3;11222:7;815:11749;11222:7;;;;:::i;:::-;815:11749;;11222:20;815:11749;;10765:11;1910:4;11169:13;;815:11749;;;10692:1;815:11749;;;;10692:1;815:11749;1660:2;;10692:1;1660:2;;815:11749;;10692:1;1660:2;;;815:11749;;;1660:2;;;;;;;;;;:::i;:::-;;;;;;815:11749;;;1660:2;;;;;;;;;;:::i;10980:21::-;;;;;;10562:773::o;815:11749::-;;10692:1;815:11749;;;;;;10692:1;815:11749;;;10692:1;815:11749;;;;;10692:1;815:11749;;;10692:1;815:11749;;10692:1;815:11749;6155:316:84;815:11749:29;;;;;;;;;;;;-1:-1:-1;815:11749:29;;;;;-1:-1:-1;815:11749:29;;;6252:23:84;6248:217;815:11749:29;;;;;;;;;;;;;;;-1:-1:-1;815:11749:29;;;;-1:-1:-1;815:11749:29;6323:4:84;815:11749:29;;;;;;;;735:10:112;815:11749:29;;6346:40:84;;815:11749:29;6346:40:84;;6323:4;6400:11;:::o;6248:217::-;6442:12;;815:11749:29;6442:12:84;:::o;6708:317::-;815:11749:29;;;;;;;;;;;;-1:-1:-1;815:11749:29;;;;;-1:-1:-1;815:11749:29;;;6802:217:84;815:11749:29;;;;;;;;;;;;;;;-1:-1:-1;815:11749:29;;;;-1:-1:-1;815:11749:29;;;;;;;;735:10:112;815:11749:29;;6900:40:84;;815:11749:29;6900:40:84;;815:11749:29;6954:11:84;:::o;2433:778:122:-;815:11749:29;;;2433:778:122;2623:2;2603:22;;2623:2;;3055:25;2839:196;;;;;;;;;;;;;;;-1:-1:-1;2839:196:122;3055:25;;:::i;:::-;3048:32;;;;;:::o;2599:606::-;3111:83;;3127:1;3111:83;3131:35;3111:83;;:::o;11630:532::-;815:11749:29;;;;;;11716:29:122;;;11761:7;;:::o;11712:444::-;815:11749:29;11812:38:122;;815:11749:29;;11873:23:122;11725:20;11873:23;815:11749:29;11725:20:122;11873:23;11808:348;11926:35;11917:44;;11926:35;;11984:46;;11725:20;11984:46;815:11749:29;;;11725:20:122;11984:46;11913:243;12060:30;12051:39;12047:109;;11913:243;11630:532::o;12047:109::-;12113:32;11725:20;12113:32;815:11749:29;;;11725:20:122;12113:32;7142:1551;;;8222:66;8209:79;;8205:164;;815:11749:29;;;;;;-1:-1:-1;815:11749:29;;;;;;;;;;;;;;;;;;;8480:24:122;;;;;;;;;-1:-1:-1;8480:24:122;815:11749:29;;;8518:20:122;8514:113;;8637:49;-1:-1:-1;8637:49:122;-1:-1:-1;7142:1551:122;:::o;8514:113::-;8554:62;-1:-1:-1;8554:62:122;8480:24;8554:62;-1:-1:-1;8554:62:122;:::o;8205:164::-;8304:54;;;8320:1;8304:54;8324:30;8304:54;;:::o","linkReferences":{}},"methodIdentifiers":{"DEFAULT_ADMIN_ROLE()":"a217fddf","PROOF_SUBMITTER_ROLE()":"5972185a","getAttestationSet()":"a845a7f3","getClientState()":"ef913a4b","getConsensusTimestamp(uint64)":"5832611b","getRoleAdmin(bytes32)":"248a9ca3","grantRole(bytes32,address)":"2f2ff15d","hasRole(bytes32,address)":"91d14854","misbehaviour(bytes)":"ddba6537","renounceRole(bytes32,address)":"36568abe","revokeRole(bytes32,address)":"d547741f","supportsInterface(bytes4)":"01ffc9a7","updateClient(bytes)":"0bece356","verifyMembership((bytes,(uint64,uint64),bytes[],bytes))":"682ed5f0","verifyNonMembership((bytes,(uint64,uint64),bytes[]))":"4d6d9ffb"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"attestorAddresses\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"minRequiredSigs\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"initialHeight\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"initialTimestampSeconds\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"roleManager\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"minRequired\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"attestationCount\",\"type\":\"uint256\"}],\"name\":\"BadQuorum\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"height\",\"type\":\"uint64\"}],\"name\":\"ConsensusTimestampNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"}],\"name\":\"DuplicateSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ECDSAInvalidSignature\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"ECDSAInvalidSignatureLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"ECDSAInvalidSignatureS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyPackets\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptySignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyValue\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FeatureNotSupported\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FrozenClientState\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"expected\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"provided\",\"type\":\"uint64\"}],\"name\":\"HeightMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expectedLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"providedLength\",\"type\":\"uint256\"}],\"name\":\"InvalidPathLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"name\":\"InvalidSignatureLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"height\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"timestamp\",\"type\":\"uint64\"}],\"name\":\"InvalidState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoAttestors\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotMember\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotNonMember\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"name\":\"SignatureInvalid\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"validSigners\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"minRequired\",\"type\":\"uint8\"}],\"name\":\"ThresholdNotMet\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"}],\"name\":\"UnknownSigner\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PROOF_SUBMITTER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAttestationSet\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"attestorAddresses\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"minRequiredSigs\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getClientState\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"revisionHeight\",\"type\":\"uint64\"}],\"name\":\"getConsensusTimestamp\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"misbehaviour\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"updateMsg\",\"type\":\"bytes\"}],\"name\":\"updateClient\",\"outputs\":[{\"internalType\":\"enum ILightClientMsgs.UpdateResult\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"proof\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revisionNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revisionHeight\",\"type\":\"uint64\"}],\"internalType\":\"struct IICS02ClientMsgs.Height\",\"name\":\"proofHeight\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"path\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"value\",\"type\":\"bytes\"}],\"internalType\":\"struct ILightClientMsgs.MsgVerifyMembership\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"verifyMembership\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"proof\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revisionNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revisionHeight\",\"type\":\"uint64\"}],\"internalType\":\"struct IICS02ClientMsgs.Height\",\"name\":\"proofHeight\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"path\",\"type\":\"bytes[]\"}],\"internalType\":\"struct ILightClientMsgs.MsgVerifyNonMembership\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"verifyNonMembership\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"AccessControlBadConfirmation()\":[{\"details\":\"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\"}],\"AccessControlUnauthorizedAccount(address,bytes32)\":[{\"details\":\"The `account` is missing a role.\"}],\"BadQuorum(uint8,uint256)\":[{\"params\":{\"attestationCount\":\"The size of the configured attestation set.\",\"minRequired\":\"The provided minimum required signatures.\"}}],\"ConsensusTimestampNotFound(uint64)\":[{\"params\":{\"height\":\"The height that has no associated timestamp.\"}}],\"DuplicateSigner(address)\":[{\"params\":{\"signer\":\"Address of the duplicate signer.\"}}],\"ECDSAInvalidSignature()\":[{\"details\":\"The signature derives the `address(0)`.\"}],\"ECDSAInvalidSignatureLength(uint256)\":[{\"details\":\"The signature has an invalid length.\"}],\"ECDSAInvalidSignatureS(bytes32)\":[{\"details\":\"The signature has an S value that is in the upper half order.\"}],\"HeightMismatch(uint64,uint64)\":[{\"params\":{\"expected\":\"The expected height from the proofHeight field.\",\"provided\":\"The height that was present in the attested payload.\"}}],\"InvalidPathLength(uint256,uint256)\":[{\"params\":{\"expectedLength\":\"The expected length of the path.\",\"providedLength\":\"The length of the provided path.\"}}],\"InvalidSignatureLength(bytes)\":[{\"params\":{\"signature\":\"The invalid signature.\"}}],\"InvalidState(uint64,uint64)\":[{\"params\":{\"height\":\"The height of the attested state.\",\"timestamp\":\"The timestamp of the attested state.\"}}],\"SignatureInvalid(bytes)\":[{\"params\":{\"signature\":\"The invalid signature.\"}}],\"ThresholdNotMet(uint256,uint8)\":[{\"params\":{\"minRequired\":\"The minimum required signatures.\",\"validSigners\":\"Number of valid, unique attestation signatures.\"}}],\"UnknownSigner(address)\":[{\"params\":{\"signer\":\"Address of the unknown signer.\"}}]},\"events\":{\"RoleAdminChanged(bytes32,bytes32,bytes32)\":{\"details\":\"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted to signal this.\"},\"RoleGranted(bytes32,address,address)\":{\"details\":\"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call. This account bears the admin role (for the granted role). Expected in cases where the role was granted using the internal {AccessControl-_grantRole}.\"},\"RoleRevoked(bytes32,address,address)\":{\"details\":\"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)\"}},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"attestorAddresses\":\"The configured attestor addresses (EOAs)\",\"initialHeight\":\"The initial known height\",\"initialTimestampSeconds\":\"The initial timestamp in seconds for the initial height\",\"minRequiredSigs\":\"The quorum threshold\",\"roleManager\":\"Address that will administer roles and be allowed to submit proofs; if zero, anyone can submit\"}},\"getAttestationSet()\":{\"details\":\"The attestation set is fixed for the initial scope; rotation is out of scope.\",\"returns\":{\"attestorAddresses\":\"The configured attestor EOA addresses\",\"minRequiredSigs\":\"The minimum number of unique valid signatures required\"}},\"getClientState()\":{\"returns\":{\"_0\":\"The client state.\"}},\"getConsensusTimestamp(uint64)\":{\"params\":{\"revisionHeight\":\"The height for which to query the timestamp\"},\"returns\":{\"_0\":\"The trusted timestamp in unix seconds\"}},\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"misbehaviour(bytes)\":{\"params\":{\"misbehaviourMsg\":\"The misbehaviour message\"}},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event.\"},\"supportsInterface(bytes4)\":{\"details\":\"Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas.\"},\"updateClient(bytes)\":{\"params\":{\"updateMsg\":\"The encoded update message e.g., an SP1 proof.\"},\"returns\":{\"_0\":\"The result of the update operation\"}},\"verifyMembership((bytes,(uint64,uint64),bytes[],bytes))\":{\"details\":\"Notice that this message is not view, as it may update the client state for caching purposes.\",\"params\":{\"msg_\":\"The membership message\"},\"returns\":{\"_0\":\"The unix timestamp of the verification height in the counterparty chain in seconds.\"}},\"verifyNonMembership((bytes,(uint64,uint64),bytes[]))\":{\"details\":\"Notice that this message is not view, as it may update the client state for caching purposes.\",\"params\":{\"msg_\":\"The membership message\"},\"returns\":{\"_0\":\"The unix timestamp of the verification height in the counterparty chain in seconds.\"}}},\"stateVariables\":{\"PROOF_SUBMITTER_ROLE\":{\"details\":\"If `address(0)` has this role, then anyone can submit proofs. If this client is used with `ICS26Router`, the router must be granted this role.\",\"return\":\"The role identifier\",\"returns\":{\"_0\":\"The role identifier\"}}},\"title\":\"Attestation-based IBC Light Client\",\"version\":1},\"userdoc\":{\"errors\":{\"BadQuorum(uint8,uint256)\":[{\"notice\":\"Reverts when the quorum threshold is zero or exceeds the attestation count.\"}],\"ConsensusTimestampNotFound(uint64)\":[{\"notice\":\"Missing trusted timestamp for the given height.\"}],\"DuplicateSigner(address)\":[{\"notice\":\"The recovered signer appears more than once among the signatures.\"}],\"EmptyPackets()\":[{\"notice\":\"The provided packet attestations were empty.\"}],\"EmptySignatures()\":[{\"notice\":\"The provided signatures were empty.\"}],\"EmptyValue()\":[{\"notice\":\"The provided membership value was empty.\"}],\"FeatureNotSupported()\":[{\"notice\":\"Reverts for functions that are out of scope for this implementation.\"}],\"FrozenClientState()\":[{\"notice\":\"Reverts when an action is attempted on a frozen client state.\"}],\"HeightMismatch(uint64,uint64)\":[{\"notice\":\"The attested height did not match the provided proof height.\"}],\"InvalidPathLength(uint256,uint256)\":[{\"notice\":\"The provided proof path length is invalid.\"}],\"InvalidSignatureLength(bytes)\":[{\"notice\":\"ECDSA signature has an invalid length.\"}],\"InvalidState(uint64,uint64)\":[{\"notice\":\"The attested state is invalid.\"}],\"NoAttestors()\":[{\"notice\":\"Reverts when the attestation set is empty during initialization.\"}],\"NotMember()\":[{\"notice\":\"The provided value is not a member of the attested set.\"}],\"NotNonMember()\":[{\"notice\":\"The attested commitment is not zero (receipt exists, so packet was received).\"}],\"SignatureInvalid(bytes)\":[{\"notice\":\"ECDSA signature failed to recover a valid signer.\"}],\"ThresholdNotMet(uint256,uint8)\":[{\"notice\":\"The number of valid unique signatures is below the required threshold.\"}],\"UnknownSigner(address)\":[{\"notice\":\"The recovered signer is not part of the attestation set.\"}]},\"kind\":\"user\",\"methods\":{\"PROOF_SUBMITTER_ROLE()\":{\"notice\":\"The role identifier for the proof submitter role\"},\"constructor\":{\"notice\":\"Initializes the attestor light client with its fixed attestor set and initial height/timestamp.\"},\"getAttestationSet()\":{\"notice\":\"Returns the attestation set configuration.\"},\"getClientState()\":{\"notice\":\"Returns the client state.\"},\"getConsensusTimestamp(uint64)\":{\"notice\":\"Returns the trusted consensus timestamp (in seconds) at the given revision height.\"},\"misbehaviour(bytes)\":{\"notice\":\"Misbehaviour handling, moves the light client to the frozen state if misbehaviour is detected\"},\"updateClient(bytes)\":{\"notice\":\"Updating the client and consensus state\"},\"verifyMembership((bytes,(uint64,uint64),bytes[],bytes))\":{\"notice\":\"Querying the membership of a key-value pair\"},\"verifyNonMembership((bytes,(uint64,uint64),bytes[]))\":{\"notice\":\"Querying the non-membership of a key\"}},\"notice\":\"Implements an IBC light client that trusts an off-chain m-of-n attestor set.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/light-clients/attestation/AttestationLightClient.sol\":\"AttestationLightClient\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[\":@openzeppelin-contracts/=node_modules/@openzeppelin/contracts/\",\":@openzeppelin-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/=node_modules/@openzeppelin/\",\":@sp1-contracts/=node_modules/sp1-contracts/contracts/src/\",\":@uniswap/permit2/=node_modules/@uniswap/permit2/\",\":forge-std/=node_modules/forge-std/src/\",\":sp1-contracts/=node_modules/sp1-contracts/\"],\"viaIR\":true},\"sources\":{\"contracts/interfaces/ILightClient.sol\":{\"keccak256\":\"0x1caae9e4f741a86c0056d5f7713a35f3bd96db7a9fd52fc9f1cf79aad76a442f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4a536db3b926560f69547c17e4f451a2631ddea0f42bd224c7fd8382d74429f6\",\"dweb:/ipfs/QmcQ33kxcmmowXgMbQGTBgiKBjF7v8UiP4y73bB9hhDizC\"]},\"contracts/light-clients/attestation/AttestationLightClient.sol\":{\"keccak256\":\"0xb287ccfd4e7b3baa99215a62484a99117b3be10d9765899c221f3fb0d54876fd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://752979b4fe813e9cee697e2c29c7b119f8f0f84e2a9b6b1d0db97685a4435660\",\"dweb:/ipfs/QmTxfSdTKcrfaKKKtsX5Wy8RVMYcyYfkKCaDm2brNYTLFz\"]},\"contracts/light-clients/attestation/errors/IAttestationLightClientErrors.sol\":{\"keccak256\":\"0x0d3592b3c36cfcde83e2510bb9179b41befb486cbb65f529ff68c09fad751564\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8d9bd1170d3954f7af6bd9fe79efbeff8f943073d27eb7bbecc8b9c66a0bdc62\",\"dweb:/ipfs/QmRuorHcJVhDJdYf7y43tyZuDowoBGkeRjH2z9C939XuDa\"]},\"contracts/light-clients/attestation/interfaces/IAttestationLightClient.sol\":{\"keccak256\":\"0x115ffce5474e6127fdb1f2b9284ea6d51ec978efd47f4425ba693c6c69d8b0af\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://bebb9e7d156b1a3ec682ff9cb8c9680b718bf0ae8e217ed153811dd399e456e8\",\"dweb:/ipfs/QmcjbxSBU4jvZMxn7PYYM6fxLCovWj1rKAtZazXY2RSA8U\"]},\"contracts/light-clients/attestation/msgs/IAttestationLightClientMsgs.sol\":{\"keccak256\":\"0x08148f1409f7e3c8968916950d920b8a4352796191875a4672ad2404e3541ef5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://94c4b12d851c5e7b581d2794c88481df658eaf55ad4e54ddef14423c90986a67\",\"dweb:/ipfs/QmZysvpbY1Xe7kNVw1iHZsPaVMUMqLauJssyrceQybBgXw\"]},\"contracts/light-clients/attestation/msgs/IAttestationMsgs.sol\":{\"keccak256\":\"0xba7901ec5fb4a4845272501a1a0b183309cd0ae37d9ec5f9e3c6ce699bfd281f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://72d0768a801a3c70910c10a1fc48c29c62d902dc602e20d72a1388ba498e8a4b\",\"dweb:/ipfs/QmUKLdbX2NwSyHFrh2WUHLm4zdFivu3Ryw2XyjT3R9Szse\"]},\"contracts/msgs/IICS02ClientMsgs.sol\":{\"keccak256\":\"0xb5fdb25319d5c32b3f527982d45ec1e9bec5215515581aee034d853006ea01a0\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6b8939bf552c62c952a491008bcd9b59ab7dda20a9482bf93438e05793881542\",\"dweb:/ipfs/QmfWmzNCp8bd4pP26Lfw5HHp4dSZnCDqZDjVN7SD8P7eDh\"]},\"contracts/msgs/ILightClientMsgs.sol\":{\"keccak256\":\"0xa0565e7748b8b3284d72e1aa6ef4cc8264fcaa5f4e0761d22d64686953db6378\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c4476010d7090bfaa74127526f2051c6bc82ff42a09b936e848880a1f15a6065\",\"dweb:/ipfs/QmY87JgRsFQXSZdGXNjNHEJCkdTHzFXH4vZEJ3q7MnHuP8\"]},\"node_modules/@openzeppelin/contracts/access/AccessControl.sol\":{\"keccak256\":\"0x1a6b4f6b7798ab80929d491b89d5427a9b3338c0fd1acd0ba325f69c6f1646af\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://7bb7f346c12a14dc622bc105ce3c47202fbc89f4b153a28a63bb68193297330c\",\"dweb:/ipfs/QmagwF8P3bUBXwdo159ueEnY9dLSvEWwK24kk2op58egwG\"]},\"node_modules/@openzeppelin/contracts/access/IAccessControl.sol\":{\"keccak256\":\"0xbff9f59c84e5337689161ce7641c0ef8e872d6a7536fbc1f5133f128887aba3c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b308f882e796f7b79c9502deacb0a62983035c6f6f4e962b319ba6a1f4a77d3d\",\"dweb:/ipfs/QmaWCW7ahEQqFjwhSUhV7Ae7WhfNvzSpE7DQ58hvEooqPL\"]},\"node_modules/@openzeppelin/contracts/utils/Context.sol\":{\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12\",\"dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF\"]},\"node_modules/@openzeppelin/contracts/utils/cryptography/ECDSA.sol\":{\"keccak256\":\"0x360cf86214a764694dae1522a38200b1737fe90e46dcf56a0f89de143071cc20\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://2e393290a46ca6d1fa1addb40709d26e1d250638ab6acdd103b5af21768ebc7b\",\"dweb:/ipfs/QmPwT3tXwQ9NbGtZ99XRq7sr8LCQP8XaCrzw49JdXGn7us\"]},\"node_modules/@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"keccak256\":\"0x2d9dc2fe26180f74c11c13663647d38e259e45f95eb88f57b61d2160b0109d3e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://81233d1f98060113d9922180bb0f14f8335856fe9f339134b09335e9f678c377\",\"dweb:/ipfs/QmWh6R35SarhAn4z2wH8SU456jJSYL2FgucfTFgbHJJN4E\"]},\"node_modules/@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x8891738ffe910f0cf2da09566928589bf5d63f4524dd734fd9cedbac3274dd5c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://971f954442df5c2ef5b5ebf1eb245d7105d9fbacc7386ee5c796df1d45b21617\",\"dweb:/ipfs/QmadRjHbkicwqwwh61raUEapaVEtaLMcYbQZWs9gUkgj3u\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.28+commit.7893614a"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"address[]","name":"attestorAddresses","type":"address[]"},{"internalType":"uint8","name":"minRequiredSigs","type":"uint8"},{"internalType":"uint64","name":"initialHeight","type":"uint64"},{"internalType":"uint64","name":"initialTimestampSeconds","type":"uint64"},{"internalType":"address","name":"roleManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"type":"error","name":"AccessControlBadConfirmation"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"type":"error","name":"AccessControlUnauthorizedAccount"},{"inputs":[{"internalType":"uint8","name":"minRequired","type":"uint8"},{"internalType":"uint256","name":"attestationCount","type":"uint256"}],"type":"error","name":"BadQuorum"},{"inputs":[{"internalType":"uint64","name":"height","type":"uint64"}],"type":"error","name":"ConsensusTimestampNotFound"},{"inputs":[{"internalType":"address","name":"signer","type":"address"}],"type":"error","name":"DuplicateSigner"},{"inputs":[],"type":"error","name":"ECDSAInvalidSignature"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"type":"error","name":"ECDSAInvalidSignatureLength"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"type":"error","name":"ECDSAInvalidSignatureS"},{"inputs":[],"type":"error","name":"EmptyPackets"},{"inputs":[],"type":"error","name":"EmptySignatures"},{"inputs":[],"type":"error","name":"EmptyValue"},{"inputs":[],"type":"error","name":"FeatureNotSupported"},{"inputs":[],"type":"error","name":"FrozenClientState"},{"inputs":[{"internalType":"uint64","name":"expected","type":"uint64"},{"internalType":"uint64","name":"provided","type":"uint64"}],"type":"error","name":"HeightMismatch"},{"inputs":[{"internalType":"uint256","name":"expectedLength","type":"uint256"},{"internalType":"uint256","name":"providedLength","type":"uint256"}],"type":"error","name":"InvalidPathLength"},{"inputs":[{"internalType":"bytes","name":"signature","type":"bytes"}],"type":"error","name":"InvalidSignatureLength"},{"inputs":[{"internalType":"uint64","name":"height","type":"uint64"},{"internalType":"uint64","name":"timestamp","type":"uint64"}],"type":"error","name":"InvalidState"},{"inputs":[],"type":"error","name":"NoAttestors"},{"inputs":[],"type":"error","name":"NotMember"},{"inputs":[],"type":"error","name":"NotNonMember"},{"inputs":[{"internalType":"bytes","name":"signature","type":"bytes"}],"type":"error","name":"SignatureInvalid"},{"inputs":[{"internalType":"uint256","name":"validSigners","type":"uint256"},{"internalType":"uint8","name":"minRequired","type":"uint8"}],"type":"error","name":"ThresholdNotMet"},{"inputs":[{"internalType":"address","name":"signer","type":"address"}],"type":"error","name":"UnknownSigner"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32","indexed":true},{"internalType":"bytes32","name":"previousAdminRole","type":"bytes32","indexed":true},{"internalType":"bytes32","name":"newAdminRole","type":"bytes32","indexed":true}],"type":"event","name":"RoleAdminChanged","anonymous":false},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32","indexed":true},{"internalType":"address","name":"account","type":"address","indexed":true},{"internalType":"address","name":"sender","type":"address","indexed":true}],"type":"event","name":"RoleGranted","anonymous":false},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32","indexed":true},{"internalType":"address","name":"account","type":"address","indexed":true},{"internalType":"address","name":"sender","type":"address","indexed":true}],"type":"event","name":"RoleRevoked","anonymous":false},{"inputs":[],"stateMutability":"view","type":"function","name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"PROOF_SUBMITTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"getAttestationSet","outputs":[{"internalType":"address[]","name":"attestorAddresses","type":"address[]"},{"internalType":"uint8","name":"minRequiredSigs","type":"uint8"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"getClientState","outputs":[{"internalType":"bytes","name":"","type":"bytes"}]},{"inputs":[{"internalType":"uint64","name":"revisionHeight","type":"uint64"}],"stateMutability":"view","type":"function","name":"getConsensusTimestamp","outputs":[{"internalType":"uint64","name":"","type":"uint64"}]},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"stateMutability":"view","type":"function","name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"grantRole"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"stateMutability":"view","type":"function","name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function","name":"misbehaviour"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"renounceRole"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"revokeRole"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"stateMutability":"view","type":"function","name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"bytes","name":"updateMsg","type":"bytes"}],"stateMutability":"nonpayable","type":"function","name":"updateClient","outputs":[{"internalType":"enum ILightClientMsgs.UpdateResult","name":"","type":"uint8"}]},{"inputs":[{"internalType":"struct ILightClientMsgs.MsgVerifyMembership","name":"msg_","type":"tuple","components":[{"internalType":"bytes","name":"proof","type":"bytes"},{"internalType":"struct IICS02ClientMsgs.Height","name":"proofHeight","type":"tuple","components":[{"internalType":"uint64","name":"revisionNumber","type":"uint64"},{"internalType":"uint64","name":"revisionHeight","type":"uint64"}]},{"internalType":"bytes[]","name":"path","type":"bytes[]"},{"internalType":"bytes","name":"value","type":"bytes"}]}],"stateMutability":"view","type":"function","name":"verifyMembership","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"struct ILightClientMsgs.MsgVerifyNonMembership","name":"msg_","type":"tuple","components":[{"internalType":"bytes","name":"proof","type":"bytes"},{"internalType":"struct IICS02ClientMsgs.Height","name":"proofHeight","type":"tuple","components":[{"internalType":"uint64","name":"revisionNumber","type":"uint64"},{"internalType":"uint64","name":"revisionHeight","type":"uint64"}]},{"internalType":"bytes[]","name":"path","type":"bytes[]"}]}],"stateMutability":"view","type":"function","name":"verifyNonMembership","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]}],"devdoc":{"kind":"dev","methods":{"constructor":{"params":{"attestorAddresses":"The configured attestor addresses (EOAs)","initialHeight":"The initial known height","initialTimestampSeconds":"The initial timestamp in seconds for the initial height","minRequiredSigs":"The quorum threshold","roleManager":"Address that will administer roles and be allowed to submit proofs; if zero, anyone can submit"}},"getAttestationSet()":{"details":"The attestation set is fixed for the initial scope; rotation is out of scope.","returns":{"attestorAddresses":"The configured attestor EOA addresses","minRequiredSigs":"The minimum number of unique valid signatures required"}},"getClientState()":{"returns":{"_0":"The client state."}},"getConsensusTimestamp(uint64)":{"params":{"revisionHeight":"The height for which to query the timestamp"},"returns":{"_0":"The trusted timestamp in unix seconds"}},"getRoleAdmin(bytes32)":{"details":"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}."},"grantRole(bytes32,address)":{"details":"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event."},"hasRole(bytes32,address)":{"details":"Returns `true` if `account` has been granted `role`."},"misbehaviour(bytes)":{"params":{"misbehaviourMsg":"The misbehaviour message"}},"renounceRole(bytes32,address)":{"details":"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event."},"revokeRole(bytes32,address)":{"details":"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event."},"supportsInterface(bytes4)":{"details":"Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas."},"updateClient(bytes)":{"params":{"updateMsg":"The encoded update message e.g., an SP1 proof."},"returns":{"_0":"The result of the update operation"}},"verifyMembership((bytes,(uint64,uint64),bytes[],bytes))":{"details":"Notice that this message is not view, as it may update the client state for caching purposes.","params":{"msg_":"The membership message"},"returns":{"_0":"The unix timestamp of the verification height in the counterparty chain in seconds."}},"verifyNonMembership((bytes,(uint64,uint64),bytes[]))":{"details":"Notice that this message is not view, as it may update the client state for caching purposes.","params":{"msg_":"The membership message"},"returns":{"_0":"The unix timestamp of the verification height in the counterparty chain in seconds."}}},"version":1},"userdoc":{"kind":"user","methods":{"PROOF_SUBMITTER_ROLE()":{"notice":"The role identifier for the proof submitter role"},"constructor":{"notice":"Initializes the attestor light client with its fixed attestor set and initial height/timestamp."},"getAttestationSet()":{"notice":"Returns the attestation set configuration."},"getClientState()":{"notice":"Returns the client state."},"getConsensusTimestamp(uint64)":{"notice":"Returns the trusted consensus timestamp (in seconds) at the given revision height."},"misbehaviour(bytes)":{"notice":"Misbehaviour handling, moves the light client to the frozen state if misbehaviour is detected"},"updateClient(bytes)":{"notice":"Updating the client and consensus state"},"verifyMembership((bytes,(uint64,uint64),bytes[],bytes))":{"notice":"Querying the membership of a key-value pair"},"verifyNonMembership((bytes,(uint64,uint64),bytes[]))":{"notice":"Querying the non-membership of a key"}},"version":1}},"settings":{"remappings":["@openzeppelin-contracts/=node_modules/@openzeppelin/contracts/","@openzeppelin-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/","@openzeppelin/=node_modules/@openzeppelin/","@sp1-contracts/=node_modules/sp1-contracts/contracts/src/","@uniswap/permit2/=node_modules/@uniswap/permit2/","forge-std/=node_modules/forge-std/src/","sp1-contracts/=node_modules/sp1-contracts/"],"optimizer":{"enabled":true,"runs":10000},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"contracts/light-clients/attestation/AttestationLightClient.sol":"AttestationLightClient"},"evmVersion":"cancun","libraries":{},"viaIR":true},"sources":{"contracts/interfaces/ILightClient.sol":{"keccak256":"0x1caae9e4f741a86c0056d5f7713a35f3bd96db7a9fd52fc9f1cf79aad76a442f","urls":["bzz-raw://4a536db3b926560f69547c17e4f451a2631ddea0f42bd224c7fd8382d74429f6","dweb:/ipfs/QmcQ33kxcmmowXgMbQGTBgiKBjF7v8UiP4y73bB9hhDizC"],"license":"MIT"},"contracts/light-clients/attestation/AttestationLightClient.sol":{"keccak256":"0xb287ccfd4e7b3baa99215a62484a99117b3be10d9765899c221f3fb0d54876fd","urls":["bzz-raw://752979b4fe813e9cee697e2c29c7b119f8f0f84e2a9b6b1d0db97685a4435660","dweb:/ipfs/QmTxfSdTKcrfaKKKtsX5Wy8RVMYcyYfkKCaDm2brNYTLFz"],"license":"MIT"},"contracts/light-clients/attestation/errors/IAttestationLightClientErrors.sol":{"keccak256":"0x0d3592b3c36cfcde83e2510bb9179b41befb486cbb65f529ff68c09fad751564","urls":["bzz-raw://8d9bd1170d3954f7af6bd9fe79efbeff8f943073d27eb7bbecc8b9c66a0bdc62","dweb:/ipfs/QmRuorHcJVhDJdYf7y43tyZuDowoBGkeRjH2z9C939XuDa"],"license":"MIT"},"contracts/light-clients/attestation/interfaces/IAttestationLightClient.sol":{"keccak256":"0x115ffce5474e6127fdb1f2b9284ea6d51ec978efd47f4425ba693c6c69d8b0af","urls":["bzz-raw://bebb9e7d156b1a3ec682ff9cb8c9680b718bf0ae8e217ed153811dd399e456e8","dweb:/ipfs/QmcjbxSBU4jvZMxn7PYYM6fxLCovWj1rKAtZazXY2RSA8U"],"license":"MIT"},"contracts/light-clients/attestation/msgs/IAttestationLightClientMsgs.sol":{"keccak256":"0x08148f1409f7e3c8968916950d920b8a4352796191875a4672ad2404e3541ef5","urls":["bzz-raw://94c4b12d851c5e7b581d2794c88481df658eaf55ad4e54ddef14423c90986a67","dweb:/ipfs/QmZysvpbY1Xe7kNVw1iHZsPaVMUMqLauJssyrceQybBgXw"],"license":"MIT"},"contracts/light-clients/attestation/msgs/IAttestationMsgs.sol":{"keccak256":"0xba7901ec5fb4a4845272501a1a0b183309cd0ae37d9ec5f9e3c6ce699bfd281f","urls":["bzz-raw://72d0768a801a3c70910c10a1fc48c29c62d902dc602e20d72a1388ba498e8a4b","dweb:/ipfs/QmUKLdbX2NwSyHFrh2WUHLm4zdFivu3Ryw2XyjT3R9Szse"],"license":"MIT"},"contracts/msgs/IICS02ClientMsgs.sol":{"keccak256":"0xb5fdb25319d5c32b3f527982d45ec1e9bec5215515581aee034d853006ea01a0","urls":["bzz-raw://6b8939bf552c62c952a491008bcd9b59ab7dda20a9482bf93438e05793881542","dweb:/ipfs/QmfWmzNCp8bd4pP26Lfw5HHp4dSZnCDqZDjVN7SD8P7eDh"],"license":"MIT"},"contracts/msgs/ILightClientMsgs.sol":{"keccak256":"0xa0565e7748b8b3284d72e1aa6ef4cc8264fcaa5f4e0761d22d64686953db6378","urls":["bzz-raw://c4476010d7090bfaa74127526f2051c6bc82ff42a09b936e848880a1f15a6065","dweb:/ipfs/QmY87JgRsFQXSZdGXNjNHEJCkdTHzFXH4vZEJ3q7MnHuP8"],"license":"MIT"},"node_modules/@openzeppelin/contracts/access/AccessControl.sol":{"keccak256":"0x1a6b4f6b7798ab80929d491b89d5427a9b3338c0fd1acd0ba325f69c6f1646af","urls":["bzz-raw://7bb7f346c12a14dc622bc105ce3c47202fbc89f4b153a28a63bb68193297330c","dweb:/ipfs/QmagwF8P3bUBXwdo159ueEnY9dLSvEWwK24kk2op58egwG"],"license":"MIT"},"node_modules/@openzeppelin/contracts/access/IAccessControl.sol":{"keccak256":"0xbff9f59c84e5337689161ce7641c0ef8e872d6a7536fbc1f5133f128887aba3c","urls":["bzz-raw://b308f882e796f7b79c9502deacb0a62983035c6f6f4e962b319ba6a1f4a77d3d","dweb:/ipfs/QmaWCW7ahEQqFjwhSUhV7Ae7WhfNvzSpE7DQ58hvEooqPL"],"license":"MIT"},"node_modules/@openzeppelin/contracts/utils/Context.sol":{"keccak256":"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2","urls":["bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12","dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF"],"license":"MIT"},"node_modules/@openzeppelin/contracts/utils/cryptography/ECDSA.sol":{"keccak256":"0x360cf86214a764694dae1522a38200b1737fe90e46dcf56a0f89de143071cc20","urls":["bzz-raw://2e393290a46ca6d1fa1addb40709d26e1d250638ab6acdd103b5af21768ebc7b","dweb:/ipfs/QmPwT3tXwQ9NbGtZ99XRq7sr8LCQP8XaCrzw49JdXGn7us"],"license":"MIT"},"node_modules/@openzeppelin/contracts/utils/introspection/ERC165.sol":{"keccak256":"0x2d9dc2fe26180f74c11c13663647d38e259e45f95eb88f57b61d2160b0109d3e","urls":["bzz-raw://81233d1f98060113d9922180bb0f14f8335856fe9f339134b09335e9f678c377","dweb:/ipfs/QmWh6R35SarhAn4z2wH8SU456jJSYL2FgucfTFgbHJJN4E"],"license":"MIT"},"node_modules/@openzeppelin/contracts/utils/introspection/IERC165.sol":{"keccak256":"0x8891738ffe910f0cf2da09566928589bf5d63f4524dd734fd9cedbac3274dd5c","urls":["bzz-raw://971f954442df5c2ef5b5ebf1eb245d7105d9fbacc7386ee5c796df1d45b21617","dweb:/ipfs/QmadRjHbkicwqwwh61raUEapaVEtaLMcYbQZWs9gUkgj3u"],"license":"MIT"}},"version":1},"id":29} \ No newline at end of file +{"abi":[{"type":"constructor","inputs":[{"name":"attestorAddresses","type":"address[]","internalType":"address[]"},{"name":"minRequiredSigs","type":"uint8","internalType":"uint8"},{"name":"initialHeight","type":"uint64","internalType":"uint64"},{"name":"initialTimestampSeconds","type":"uint64","internalType":"uint64"},{"name":"roleManager","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"DEFAULT_ADMIN_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"PROOF_SUBMITTER_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"getAttestationSet","inputs":[],"outputs":[{"name":"attestorAddresses","type":"address[]","internalType":"address[]"},{"name":"minRequiredSigs","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"getClientState","inputs":[],"outputs":[{"name":"","type":"bytes","internalType":"bytes"}],"stateMutability":"view"},{"type":"function","name":"getConsensusTimestamp","inputs":[{"name":"revisionHeight","type":"uint64","internalType":"uint64"}],"outputs":[{"name":"","type":"uint64","internalType":"uint64"}],"stateMutability":"view"},{"type":"function","name":"getRoleAdmin","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"grantRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"hasRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"misbehaviour","inputs":[{"name":"","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"view"},{"type":"function","name":"renounceRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"callerConfirmation","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"revokeRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"updateClient","inputs":[{"name":"updateMsg","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"","type":"uint8","internalType":"enum ILightClientMsgs.UpdateResult"}],"stateMutability":"nonpayable"},{"type":"function","name":"verifyMembership","inputs":[{"name":"msg_","type":"tuple","internalType":"struct ILightClientMsgs.MsgVerifyMembership","components":[{"name":"proof","type":"bytes","internalType":"bytes"},{"name":"proofHeight","type":"tuple","internalType":"struct IICS02ClientMsgs.Height","components":[{"name":"revisionNumber","type":"uint64","internalType":"uint64"},{"name":"revisionHeight","type":"uint64","internalType":"uint64"}]},{"name":"path","type":"bytes[]","internalType":"bytes[]"},{"name":"value","type":"bytes","internalType":"bytes"}]}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"verifyNonMembership","inputs":[{"name":"msg_","type":"tuple","internalType":"struct ILightClientMsgs.MsgVerifyNonMembership","components":[{"name":"proof","type":"bytes","internalType":"bytes"},{"name":"proofHeight","type":"tuple","internalType":"struct IICS02ClientMsgs.Height","components":[{"name":"revisionNumber","type":"uint64","internalType":"uint64"},{"name":"revisionHeight","type":"uint64","internalType":"uint64"}]},{"name":"path","type":"bytes[]","internalType":"bytes[]"}]}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"event","name":"RoleAdminChanged","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"previousAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"newAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"error","name":"AccessControlBadConfirmation","inputs":[]},{"type":"error","name":"AccessControlUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"},{"name":"neededRole","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"BadQuorum","inputs":[{"name":"minRequired","type":"uint8","internalType":"uint8"},{"name":"attestationCount","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ConsensusTimestampNotFound","inputs":[{"name":"height","type":"uint64","internalType":"uint64"}]},{"type":"error","name":"DuplicateSigner","inputs":[{"name":"signer","type":"address","internalType":"address"}]},{"type":"error","name":"ECDSAInvalidSignature","inputs":[]},{"type":"error","name":"ECDSAInvalidSignatureLength","inputs":[{"name":"length","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ECDSAInvalidSignatureS","inputs":[{"name":"s","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"EmptyPackets","inputs":[]},{"type":"error","name":"EmptySignatures","inputs":[]},{"type":"error","name":"EmptyValue","inputs":[]},{"type":"error","name":"FeatureNotSupported","inputs":[]},{"type":"error","name":"FrozenClientState","inputs":[]},{"type":"error","name":"HeightMismatch","inputs":[{"name":"expected","type":"uint64","internalType":"uint64"},{"name":"provided","type":"uint64","internalType":"uint64"}]},{"type":"error","name":"InvalidPathLength","inputs":[{"name":"expectedLength","type":"uint256","internalType":"uint256"},{"name":"providedLength","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"InvalidSignatureLength","inputs":[{"name":"signature","type":"bytes","internalType":"bytes"}]},{"type":"error","name":"InvalidState","inputs":[{"name":"height","type":"uint64","internalType":"uint64"},{"name":"timestamp","type":"uint64","internalType":"uint64"}]},{"type":"error","name":"NoAttestors","inputs":[]},{"type":"error","name":"NotMember","inputs":[]},{"type":"error","name":"NotNonMember","inputs":[]},{"type":"error","name":"SignatureInvalid","inputs":[{"name":"signature","type":"bytes","internalType":"bytes"}]},{"type":"error","name":"ThresholdNotMet","inputs":[{"name":"validSigners","type":"uint256","internalType":"uint256"},{"name":"minRequired","type":"uint8","internalType":"uint8"}]},{"type":"error","name":"UnknownSigner","inputs":[{"name":"signer","type":"address","internalType":"address"}]}],"bytecode":{"object":"0x60806040523461032d57611f568038038061001981610349565b928339810160a08282031261032d5781516001600160401b03811161032d57820181601f8201121561032d578051916001600160401b0383116102c8578260051b916020610068818501610349565b8095815201906020829482010192831161032d57602001905b8282106103315750505060208301519260ff841680940361032d576100a860408201610382565b6100c060806100b960608501610382565b930161036e565b9284511561031e57851515806102f2575b855190156102dc575060405195608087016001600160401b038111888210176102c857604052858752602087019081526060604088019360018060401b03169788855201915f835286519060018060401b0382116102c8576801000000000000000082116102c85760015482600155808310610284575b5060015f5260205f205f5b838110610267575050505060ff90511669ff00000000000000000060025493610100600160481b03905160081b169251151560481b169260018060501b0319161717176002555f5b83518110156101fb5760018060a01b0360208260051b8601015116805f52600360205260ff60405f2054166101e957906001915f52600360205260405f208260ff198254161790550161019b565b637010e27960e11b5f5260045260245ffd5b505f84815260046020526040902080546001600160401b0319166001600160401b039092169190911790556001600160a01b03811661024e575061023d61048c565b505b6040516119a7908161050f8239f35b8061025b61026192610396565b5061040c565b5061023f565b82516001600160a01b031681830155602090920191600101610153565b60015f527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf69081019083015b8181106102bd5750610148565b5f81556001016102b0565b634e487b7160e01b5f52604160045260245ffd5b866365846b7f60e01b5f5260045260245260445ffd5b5084515f19870160ff811161030a5760ff16106100d1565b634e487b7160e01b5f52601160045260245ffd5b6343d0a89360e11b5f5260045ffd5b5f80fd5b6020809161033e8461036e565b815201910190610081565b6040519190601f01601f191682016001600160401b038111838210176102c857604052565b51906001600160a01b038216820361032d57565b51906001600160401b038216820361032d57565b6001600160a01b0381165f9081525f516020611f365f395f51905f52602052604090205460ff16610407576001600160a01b03165f8181525f516020611f365f395f51905f5260205260408120805460ff191660011790553391905f516020611eb65f395f51905f528180a4600190565b505f90565b6001600160a01b0381165f9081525f516020611ed65f395f51905f52602052604090205460ff16610407576001600160a01b03165f8181525f516020611ed65f395f51905f5260205260408120805460ff191660011790553391905f516020611f165f395f51905f52905f516020611eb65f395f51905f529080a4600190565b5f80525f516020611ed65f395f51905f526020525f516020611ef65f395f51905f525460ff1661050a575f8080525f516020611ed65f395f51905f526020525f516020611ef65f395f51905f52805460ff1916600117905533905f516020611f165f395f51905f525f516020611eb65f395f51905f528280a4600190565b5f9056fe6080806040526004361015610012575f80fd5b5f3560e01c90816301ffc9a7146106ab575080630bece356146105e8578063248a9ca3146105be5780632f2ff15d1461058f57806336568abe146105335780634d6d9ffb146104865780635832611b146104405780635972185a14610406578063682ed5f01461035157806391d1485414610308578063a217fddf146102ee578063a845a7f314610261578063d547741f1461022b578063ddba65371461015f5763ef913a4b146100c1575f80fd5b3461015b575f60031936011261015b576101576040516020808201526080604082015261014b816100f460c08201611228565b60ff600254818116606085015267ffffffffffffffff8160081c16608085015260481c16151560a0830152037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810183528261085e565b604051918291826107cd565b0390f35b5f80fd5b3461015b5761016d36610749565b505060ff60025460481c16610203575f80527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e06020527f6e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac475460ff16156101f6575b7fda81d7c2000000000000000000000000000000000000000000000000000000005f5260045ffd5b6101fe611277565b6101ce565b7f928b1233000000000000000000000000000000000000000000000000000000005f5260045ffd5b3461015b5761025f61023c3661079a565b9061025a610255825f525f602052600160405f20015490565b6112ff565b61175e565b005b3461015b575f60031936011261015b5760ff6002541660405161028e8161028781611228565b038261085e565b60405190604082019260408352815180945260206060840192015f945b8086106102c057505082935060208301520390f35b909260208060019273ffffffffffffffffffffffffffffffffffffffff8751168152019401950194906102ab565b3461015b575f60031936011261015b5760206040515f8152f35b3461015b576103163661079a565b905f525f60205273ffffffffffffffffffffffffffffffffffffffff60405f2091165f52602052602060ff60405f2054166040519015158152f35b3461015b57602060031936011261015b5760043567ffffffffffffffff811161015b5760a0600319823603011261015b5760ff60025460481c16610203575f80527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e060209081527f6e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac475490916103f19160ff16156103f9575b6004016110cb565b604051908152f35b610401611277565b6103e9565b3461015b575f60031936011261015b5760206040517fbd893629a699470e4ec82a5715bb4981fdaacc5d0a728bf5f55b801d8f4ef10b8152f35b3461015b57602060031936011261015b5760043567ffffffffffffffff811680910361015b575f526004602052602067ffffffffffffffff60405f205416604051908152f35b3461015b57602060031936011261015b5760043567ffffffffffffffff811161015b576080600319823603011261015b5760ff60025460481c16610203575f80527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e060209081527f6e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac475490916103f19160ff1615610526575b600401610ef5565b61052e611277565b61051e565b3461015b576105413661079a565b3373ffffffffffffffffffffffffffffffffffffffff8216036105675761025f9161175e565b7f6697b232000000000000000000000000000000000000000000000000000000005f5260045ffd5b3461015b5761025f6105a03661079a565b906105b9610255825f525f602052600160405f20015490565b61168c565b3461015b57602060031936011261015b5760206103f16004355f525f602052600160405f20015490565b3461015b576105f636610749565b60ff60025460481c16610203575f80527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e06020527f6e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac475461065e929060ff161561069e57610a3c565b6040516003821015610671576020918152f35b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b6106a6611277565b610a3c565b3461015b57602060031936011261015b57600435907fffffffff00000000000000000000000000000000000000000000000000000000821680920361015b57817f7965db0b000000000000000000000000000000000000000000000000000000006020931490811561071f575b5015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501483610718565b90602060031983011261015b5760043567ffffffffffffffff811161015b578260238201121561015b5780600401359267ffffffffffffffff841161015b576024848301011161015b576024019190565b600319604091011261015b576004359060243573ffffffffffffffffffffffffffffffffffffffff8116810361015b5790565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602060409481855280519182918282880152018686015e5f8582860101520116010190565b6040810190811067ffffffffffffffff82111761083157604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761083157604052565b92919267ffffffffffffffff821161083157604051916108e760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116018461085e565b82948184528183011161015b578281602093845f960137010152565b9080601f8301121561015b5781602061091e9335910161089f565b90565b67ffffffffffffffff81116108315760051b60200190565b60208183031261015b5780359067ffffffffffffffff821161015b57019060408282031261015b576040519161096e83610815565b803567ffffffffffffffff811161015b578261098b918301610903565b835260208101359067ffffffffffffffff821161015b57019080601f8301121561015b5781356109ba81610921565b926109c8604051948561085e565b81845260208085019260051b8201019183831161015b5760208201905b8382106109f9575050505050602082015290565b813567ffffffffffffffff811161015b57602091610a1c87848094880101610903565b8152019101906109e5565b519067ffffffffffffffff8216820361015b57565b610a4891810190610939565b60205f818351604051918183925191829101835e8101838152039060025afa15610c915760205f8051604051838101917f01000000000000000000000000000000000000000000000000000000000000008352602182015260218152610aaf60418261085e565b604051918291518091835e8101838152039060025afa15610c9157610ada5f516020830151906113eb565b5160408180518101031261015b57604051610af481610815565b610b0f6040610b0560208501610a27565b9384845201610a27565b67ffffffffffffffff60208301938285521680151580610c7e575b15610c4457505067ffffffffffffffff8151165f52600460205267ffffffffffffffff60405f20541680610bf3575067ffffffffffffffff9051918183169260025490838260081c168511610bb6575b50505116905f52600460205260405f20907fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008254161790555f90565b68ffffffffffffffff007fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff9160081b169116176002555f80610b7a565b9167ffffffffffffffff9150511603610c0b57600290565b69010000000000000000007fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff6002541617600255600190565b67ffffffffffffffff92507fdcbc5460000000000000000000000000000000000000000000000000000000005f526004521660245260445ffd5b5067ffffffffffffffff82161515610b2a565b6040513d5f823e3d90fd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561015b570180359067ffffffffffffffff821161015b57602001918160051b3603831361015b57565b3567ffffffffffffffff8116810361015b5790565b15610d0d5750565b67ffffffffffffffff907ff7caaa5c000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561015b570180359067ffffffffffffffff821161015b5760200191813603831361015b57565b60208183031261015b5780519067ffffffffffffffff821161015b57019060408282031261015b5760405191610dc983610815565b610dd281610a27565b835260208101519067ffffffffffffffff821161015b570181601f8201121561015b57805190610e0182610921565b92610e0f604051948561085e565b82845260208085019360061b8301019181831161015b57602001925b828410610e3e5750505050602082015290565b60408483031261015b5760206040918251610e5881610815565b865181528287015183820152815201930192610e2b565b15610e78575050565b9067ffffffffffffffff80927fc7441689000000000000000000000000000000000000000000000000000000005f52166004521660245260445ffd5b8051821015610ec85760209160051b010190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b6060810190610f048282610c9c565b90506001610f128484610c9c565b9290500361109b5750610fb8610f2a60408301610cf0565b9267ffffffffffffffff841692835f526004602052610fb367ffffffffffffffff60405f20541694610f5e87871515610d05565b610f9e610f76610f6e8580610d43565b810190610939565b610f8e610f838251611365565b6020830151906113eb565b5160208082518301019101610d94565b9667ffffffffffffffff885116918214610e6f565b610c9c565b15610ec857610fd3610fcc82602093610d43565b369161089f565b818151910120920180515115611073575f5b8151805182101561104b57610ffb828692610eb4565b51511461100a57600101610fe5565b60209293506110199151610eb4565b5101516110235790565b7f9a960b4f000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f291fc442000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f1e6c84da000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f88b3170e000000000000000000000000000000000000000000000000000000005f52600160045260245260445ffd5b608081016110d98183610d43565b9050156112005760608201906110ef8284610c9c565b905060016110fd8486610c9c565b9290500361109b575061111260408401610cf0565b9061117467ffffffffffffffff831693845f52600460205261116e67ffffffffffffffff60405f2054169561114986881515610d05565b611159610f76610f6e8a80610d43565b9567ffffffffffffffff875116918214610e6f565b85610c9c565b15610ec85760209161118c610fcc8361119894610d43565b83815191012095610d43565b908092918101031261015b576020903591019081515115611073575f5b8251805182101561104b576111cb828792610eb4565b515114806111e8575b6111e0576001016111b5565b505050905090565b508160206111f7838651610eb4565b510151146111d4565b7f1208b21b000000000000000000000000000000000000000000000000000000005f5260045ffd5b602060015491828152019060015f5260205f20905f5b81811061124b5750505090565b825473ffffffffffffffffffffffffffffffffffffffff1684526020909301926001928301920161123e565b335f9081527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e0602052604090205460ff16156112af57565b7fe2517d3f000000000000000000000000000000000000000000000000000000005f52336004527fbd893629a699470e4ec82a5715bb4981fdaacc5d0a728bf5f55b801d8f4ef10b60245260445ffd5b805f525f60205260405f2073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f205416156113365750565b7fe2517d3f000000000000000000000000000000000000000000000000000000005f523360045260245260445ffd5b5f60208092604051918183925191829101835e8101838152039060025afa15610c915760205f8051604051838101917f020000000000000000000000000000000000000000000000000000000000000083526021820152602181526113cb60418261085e565b604051918291518091835e8101838152039060025afa15610c91575f5190565b91909182511561166457825160ff60025416907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82019060ff82116116375760ff8651921610156116095750508251927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061147e61146886610921565b95611476604051978861085e565b808752610921565b013660208601375f5b81518110156116025761149a8183610eb4565b5160418151036115cc5773ffffffffffffffffffffffffffffffffffffffff6114cf6114c68387611826565b90929192611860565b169081156115925750805f52600360205260ff60405f20541615611567575f5b82811061150c5750906001916115058288610eb4565b5201611487565b8173ffffffffffffffffffffffffffffffffffffffff61152c838a610eb4565b51161461153b576001016114ef565b507fe021c4f2000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b7fd7e8a2c2000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b6115c8906040519182917f9e3c1b3d000000000000000000000000000000000000000000000000000000008352600483016107cd565b0390fd5b6115c8906040519182917f2ee17a3d000000000000000000000000000000000000000000000000000000008352600483016107cd565b5050509050565b7f378b0805000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b7f301b38b6000000000000000000000000000000000000000000000000000000005f5260045ffd5b805f525f60205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260ff60405f205416155f1461175857805f525f60205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260405f2060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905573ffffffffffffffffffffffffffffffffffffffff339216907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d5f80a4600190565b50505f90565b805f525f60205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260ff60405f2054165f1461175857805f525f60205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260405f207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00815416905573ffffffffffffffffffffffffffffffffffffffff339216907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b5f80a4600190565b81519190604183036118565761184f9250602082015190606060408401519301515f1a9061190b565b9192909190565b50505f9160029190565b60048110156106715780611872575050565b600181036118a2577ff645eedf000000000000000000000000000000000000000000000000000000005f5260045ffd5b600281036118d657507ffce698f7000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b6003146118e05750565b7fd78bce0c000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841161198f579160209360809260ff5f9560405194855216868401526040830152606082015282805260015afa15610c91575f5173ffffffffffffffffffffffffffffffffffffffff81161561198557905f905f90565b505f906001905f90565b5050505f916003919056fea164736f6c634300081c000a2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e06e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac47bd893629a699470e4ec82a5715bb4981fdaacc5d0a728bf5f55b801d8f4ef10bad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5"}} diff --git a/ibc-solidity/abi/bytecode/BesuIBFT2LightClient.json b/ibc-solidity/abi/bytecode/BesuIBFT2LightClient.json new file mode 100644 index 000000000..c8cbdaa4e --- /dev/null +++ b/ibc-solidity/abi/bytecode/BesuIBFT2LightClient.json @@ -0,0 +1 @@ +{"abi":[{"type":"constructor","inputs":[{"name":"ibcRouter","type":"address","internalType":"address"},{"name":"initialTrustedHeight","type":"uint64","internalType":"uint64"},{"name":"initialTrustedTimestamp","type":"uint64","internalType":"uint64"},{"name":"initialTrustedStorageRoot","type":"bytes32","internalType":"bytes32"},{"name":"initialTrustedValidators","type":"address[]","internalType":"address[]"},{"name":"trustingPeriod","type":"uint64","internalType":"uint64"},{"name":"maxClockDrift","type":"uint64","internalType":"uint64"},{"name":"roleManager","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"DEFAULT_ADMIN_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"PROOF_SUBMITTER_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"getClientState","inputs":[],"outputs":[{"name":"","type":"bytes","internalType":"bytes"}],"stateMutability":"view"},{"type":"function","name":"getConsensusState","inputs":[{"name":"revisionHeight","type":"uint64","internalType":"uint64"}],"outputs":[{"name":"","type":"bytes","internalType":"bytes"}],"stateMutability":"view"},{"type":"function","name":"getRoleAdmin","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"grantRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"hasRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"misbehaviour","inputs":[{"name":"","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"view"},{"type":"function","name":"renounceRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"callerConfirmation","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"revokeRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"updateClient","inputs":[{"name":"updateMsg","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"","type":"uint8","internalType":"enum ILightClientMsgs.UpdateResult"}],"stateMutability":"nonpayable"},{"type":"function","name":"verifyMembership","inputs":[{"name":"msg_","type":"tuple","internalType":"struct ILightClientMsgs.MsgVerifyMembership","components":[{"name":"proof","type":"bytes","internalType":"bytes"},{"name":"proofHeight","type":"tuple","internalType":"struct IICS02ClientMsgs.Height","components":[{"name":"revisionNumber","type":"uint64","internalType":"uint64"},{"name":"revisionHeight","type":"uint64","internalType":"uint64"}]},{"name":"path","type":"bytes[]","internalType":"bytes[]"},{"name":"value","type":"bytes","internalType":"bytes"}]}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"verifyNonMembership","inputs":[{"name":"msg_","type":"tuple","internalType":"struct ILightClientMsgs.MsgVerifyNonMembership","components":[{"name":"proof","type":"bytes","internalType":"bytes"},{"name":"proofHeight","type":"tuple","internalType":"struct IICS02ClientMsgs.Height","components":[{"name":"revisionNumber","type":"uint64","internalType":"uint64"},{"name":"revisionHeight","type":"uint64","internalType":"uint64"}]},{"name":"path","type":"bytes[]","internalType":"bytes[]"}]}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"event","name":"RoleAdminChanged","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"previousAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"newAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"error","name":"AccessControlBadConfirmation","inputs":[]},{"type":"error","name":"AccessControlUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"},{"name":"neededRole","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"ConflictingConsensusState","inputs":[{"name":"revisionHeight","type":"uint64","internalType":"uint64"}]},{"type":"error","name":"ConsensusStateExpired","inputs":[{"name":"trustedTimestamp","type":"uint64","internalType":"uint64"},{"name":"currentTimestamp","type":"uint256","internalType":"uint256"},{"name":"trustingPeriod","type":"uint64","internalType":"uint64"}]},{"type":"error","name":"ConsensusStateNotFound","inputs":[{"name":"revisionHeight","type":"uint64","internalType":"uint64"}]},{"type":"error","name":"DuplicateCommitSealSigner","inputs":[{"name":"signer","type":"address","internalType":"address"}]},{"type":"error","name":"DuplicateValidator","inputs":[{"name":"validator","type":"address","internalType":"address"}]},{"type":"error","name":"EmptyValidatorSet","inputs":[]},{"type":"error","name":"HeaderFromFuture","inputs":[{"name":"currentTimestamp","type":"uint256","internalType":"uint256"},{"name":"headerTimestamp","type":"uint256","internalType":"uint256"},{"name":"maxClockDrift","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"InsufficientTrustedValidatorOverlap","inputs":[{"name":"actual","type":"uint256","internalType":"uint256"},{"name":"required","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"InsufficientValidatorQuorum","inputs":[{"name":"actual","type":"uint256","internalType":"uint256"},{"name":"required","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"InvalidCommitSeal","inputs":[]},{"type":"error","name":"InvalidCommitmentValue","inputs":[{"name":"expectedValue","type":"bytes32","internalType":"bytes32"},{"name":"actualValue","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"InvalidDifficulty","inputs":[{"name":"actualDifficulty","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"InvalidECDSASignatureLength","inputs":[{"name":"length","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"InvalidExtraDataFormat","inputs":[{"name":"itemsLength","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"InvalidHeaderFormat","inputs":[{"name":"itemsLength","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"InvalidHeaderHeight","inputs":[]},{"type":"error","name":"InvalidHeaderTimestamp","inputs":[]},{"type":"error","name":"InvalidMixHash","inputs":[{"name":"actualMixHash","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"InvalidNonce","inputs":[{"name":"actualNonce","type":"bytes","internalType":"bytes"}]},{"type":"error","name":"InvalidOmmersHash","inputs":[{"name":"actualOmmersHash","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"InvalidPathLength","inputs":[{"name":"expectedLength","type":"uint256","internalType":"uint256"},{"name":"actualLength","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"InvalidRevisionNumber","inputs":[{"name":"providedRevisionNumber","type":"uint64","internalType":"uint64"}]},{"type":"error","name":"InvalidValidatorAddress","inputs":[{"name":"validator","type":"address","internalType":"address"}]},{"type":"error","name":"InvalidValidatorAddressLength","inputs":[{"name":"length","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"InvalidValueLength","inputs":[{"name":"expectedLength","type":"uint256","internalType":"uint256"},{"name":"actualLength","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"UnsupportedMisbehaviour","inputs":[]},{"type":"error","name":"ValueExists","inputs":[{"name":"actualValue","type":"bytes32","internalType":"bytes32"}]}],"bytecode":{"object":"0x6080604052346103d8576138eb80380380610019816103dc565b928339810190610100818303126103d85761003381610401565b9061004060208201610415565b9061004d60408201610415565b92606082015191608081015160018060401b0381116103d85781019286601f850112156103d8578351966001600160401b03881161037f578760051b9460206100978188016103dc565b809a81520190602082978201019283116103d857602001905b8282106103c0575050506100c660a08301610415565b956100df60e06100d860c08601610415565b9401610401565b956001600160401b03169081156103b1576001600160401b03169283156103a257885115610393575f5b89518110156101bf576001600160a01b03610124828c610429565b511615610198575f5b81811061013d5750600101610109565b6001600160a01b0361014f828d610429565b51166001600160a01b03610163848e610429565b5116146101725760010161012d565b6001600160a01b03610184838d610429565b511663107f863360e21b5f5260045260245ffd5b6001600160a01b03906101ab908b610429565b51166359bff38760e01b5f5260045260245ffd5b5060408051979896978a979181016001600160401b0381118282101761037f576040525f81526020810190848252604051926080840198848a1060018060401b038b111761037f576040998a526001600160a01b031680855260208086018490526001600160401b03928316868c01819052878416606090970196909652600180546001600160a01b031916909217825592516002805495516fffffffffffffffff0000000000000000908d1b81169285166001600160801b03199788161792909217815560038054988d1b90921697909516909517959095179093555f948552600490529590922080546001600160401b031916949094178455830191909155925193910191831161037f5768010000000000000000831161037f578154838355808410610359575b50905f5260205f205f5b83811061033c57846001600160a01b0381166103235750610312610547565b505b60405161328190816105ca8239f35b8061033061033692610451565b506104c7565b50610314565b82516001600160a01b0316818301556020909201916001016102f3565b825f528360205f2091820191015b81811061037457506102e9565b5f8155600101610367565b634e487b7160e01b5f52604160045260245ffd5b63339e1ffb60e01b5f5260045ffd5b63574f4e6160e01b5f5260045ffd5b6359d119e360e01b5f5260045ffd5b602080916103cd84610401565b8152019101906100b0565b5f80fd5b6040519190601f01601f191682016001600160401b0381118382101761037f57604052565b51906001600160a01b03821682036103d857565b51906001600160401b03821682036103d857565b805182101561043d5760209160051b010190565b634e487b7160e01b5f52603260045260245ffd5b6001600160a01b0381165f9081525f5160206138cb5f395f51905f52602052604090205460ff166104c2576001600160a01b03165f8181525f5160206138cb5f395f51905f5260205260408120805460ff191660011790553391905f51602061384b5f395f51905f528180a4600190565b505f90565b6001600160a01b0381165f9081525f51602061386b5f395f51905f52602052604090205460ff166104c2576001600160a01b03165f8181525f51602061386b5f395f51905f5260205260408120805460ff191660011790553391905f5160206138ab5f395f51905f52905f51602061384b5f395f51905f529080a4600190565b5f80525f51602061386b5f395f51905f526020525f51602061388b5f395f51905f525460ff166105c5575f8080525f51602061386b5f395f51905f526020525f51602061388b5f395f51905f52805460ff1916600117905533905f5160206138ab5f395f51905f525f51602061384b5f395f51905f528280a4600190565b5f9056fe60806040526004361015610011575f80fd5b5f3560e01c806301ffc9a7146100f45780630bece356146100ef578063248a9ca3146100ea5780632f2ff15d146100e557806336568abe146100e05780634d6d9ffb146100db5780635972185a146100d6578063682ed5f0146100d157806391d14854146100cc578063a217fddf146100c7578063d547741f146100c2578063ddba6537146100bd578063edce8bdc146100b85763ef913a4b146100b3575f80fd5b6109c8565b61095e565b61088b565b61085c565b610842565b6107f4565b6105e6565b6105ac565b6103ac565b610350565b61031a565b6102b5565b610217565b34610195576020600319360112610195576004357fffffffff00000000000000000000000000000000000000000000000000000000811680910361019557807f7965db0b000000000000000000000000000000000000000000000000000000006020921490811561016b575b506040519015158152f35b7f01ffc9a7000000000000000000000000000000000000000000000000000000009150145f610160565b5f80fd5b9060206003198301126101955760043567ffffffffffffffff811161019557826023820112156101955780600401359267ffffffffffffffff84116101955760248483010111610195576024019190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b346101955761028161022836610199565b5f80527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e06020527f6e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac475490919060ff161561029957610d17565b6040516003821015610294576020918152f35b6101ea565b6102a1611275565b610d17565b90816020910312610195573590565b346101955760206003193601126101955760206102df6004355f525f602052600160405f20015490565b604051908152f35b6003196040910112610195576004359060243573ffffffffffffffffffffffffffffffffffffffff811681036101955790565b346101955761034e61032b366102e7565b90610349610344825f525f602052600160405f20015490565b6112fd565b612181565b005b346101955761035e366102e7565b3373ffffffffffffffffffffffffffffffffffffffff8216036103845761034e91612258565b7f6697b232000000000000000000000000000000000000000000000000000000005f5260045ffd5b346101955760206003193601126101955760043567ffffffffffffffff8111610195578060040160806003198336030112610195575f80527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e060205260ff7f6e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac4754161561059f575b61044761044260248401611133565b61136a565b60648201916001610458848461113d565b90500361056157906104a96104966104a261049d61049661049061048961048460446104e09a01611133565b611b0f565b988761113d565b9061120f565b3691610aff565b61232d565b92806111be565b906001840154906040516104d7816104c960208201948560209181520190565b03601f198101835282610aaf565b519020916123bb565b805161051f5761051b61050b6104fe845467ffffffffffffffff1690565b67ffffffffffffffff1690565b6040519081529081906020820190565b0390f35b61053361052e61055e92612500565b61252d565b7fd039601e000000000000000000000000000000000000000000000000000000005f52600452602490565b5ffd5b61055e61056e848461113d565b7f88b3170e000000000000000000000000000000000000000000000000000000005f52600160045260245250604490565b6105a7611275565b610433565b34610195575f6003193601126101955760206040517fbd893629a699470e4ec82a5715bb4981fdaacc5d0a728bf5f55b801d8f4ef10b8152f35b346101955760206003193601126101955760043567ffffffffffffffff8111610195578060040160a06003198336030112610195575f80527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e060205260ff7f6e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac475416156107e7575b61067c61044260248401611133565b6064820191600161068d848461113d565b90500361056157608481019060206106a583856111be565b9050036107a957906106f46104966106ed6106e56106de61049d6104966104906106d761048460446107149c01611133565b9b8b61113d565b94876111be565b8101906102a6565b94806111be565b906001850154906040516104d7816104c960208201948560209181520190565b8051156107755761052e61072791612500565b908082036107475761051b61050b6104fe855467ffffffffffffffff1690565b7f56ed1b63000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b61055e827f56ed1b63000000000000000000000000000000000000000000000000000000005f52906044916004525f602452565b61055e6107b683856111be565b7f24fadac8000000000000000000000000000000000000000000000000000000005f52602060045260245250604490565b6107ef611275565b61066d565b3461019557602060ff610836610809366102e7565b905f525f845260405f209073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b54166040519015158152f35b34610195575f6003193601126101955760206040515f8152f35b346101955761034e61086d366102e7565b90610886610344825f525f602052600160405f20015490565b612258565b346101955761089936610199565b50505f80527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e06020527f6e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac475460ff1615610915575b7f2c1ed462000000000000000000000000000000000000000000000000000000005f5260045ffd5b61091d611275565b6108ed565b67ffffffffffffffff81160361019557565b601f19601f602060409481855280519182918282880152018686015e5f8582860101520116010190565b346101955760206003193601126101955761051b61098160043561048481610922565b6109bc67ffffffffffffffff8254166104c9600184015493604051948593602085015260408401526060808401526002608084019101611228565b60405191829182610934565b34610195575f6003193601126101955761051b60405173ffffffffffffffffffffffffffffffffffffffff60015416602082015267ffffffffffffffff600254818116604084015260401c16606082015267ffffffffffffffff600354818116608084015260401c1660a082015260a081526109bc60c082610aaf565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6060810190811067ffffffffffffffff821117610a8e57604052565b610a45565b6040810190811067ffffffffffffffff821117610a8e57604052565b90601f601f19910116810190811067ffffffffffffffff821117610a8e57604052565b60405190610ae1604083610aaf565b565b67ffffffffffffffff8111610a8e57601f01601f191660200190565b929192610b0b82610ae3565b91610b196040519384610aaf565b829481845281830111610195578281602093845f960137010152565b9080601f8301121561019557816020610b5093359101610aff565b90565b6020818303126101955780359067ffffffffffffffff8211610195570180820391608083126101955760405192610b8984610a72565b823567ffffffffffffffff811161019557604091610bac84601f19938701610b35565b8652011261019557604051610bc081610a93565b6020830135610bce81610922565b81526040830135610bde81610922565b60208201526020840152606082013567ffffffffffffffff811161019557610c069201610b35565b604082015290565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b9060018201809211610c4957565b610c0e565b91908201809211610c4957565b908160011b9180830460021490151715610c4957565b81519167ffffffffffffffff8311610a8e57680100000000000000008311610a8e578154838355808410610cf1575b506020610cb29101915f5260205f2090565b5f5b838110610cc15750505050565b6001906020610ce4855173ffffffffffffffffffffffffffffffffffffffff1690565b9401938184015501610cb4565b825f528360205f2091820191015b818110610d0c5750610ca0565b5f8155600101610cff565b610d2391810190610b53565b906020820191610d3f61044284515167ffffffffffffffff1690565b610d4981516115fb565b92604084019367ffffffffffffffff610d6a865167ffffffffffffffff1690565b161561110b576080810192610d8a6104fe855167ffffffffffffffff1690565b156110e3576003549267ffffffffffffffff604085901c16610dac8142610c4e565b865167ffffffffffffffff169081116110a45750505160200151610deb90610ddd9067ffffffffffffffff16611b0f565b9367ffffffffffffffff1690565b67ffffffffffffffff8116801515908161107b575b50611026575090610e6e91610e2f6002610e27610e1c85611b66565b60c086015190611c7b565b950185611e94565b610e3f60a0830194855190611fb9565b60406060610e6260015473ffffffffffffffffffffffffffffffffffffffff1690565b9301519101519161205c565b610e9b610e83865167ffffffffffffffff1690565b67ffffffffffffffff165f52600460205260405f2090565b610eb06104fe825467ffffffffffffffff1690565b610fb45750916002610f2e928694610f21610eec610edd610e83610f3c9a9b5167ffffffffffffffff1690565b955167ffffffffffffffff1690565b859067ffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000825416179055565b6001840155519101610c71565b5167ffffffffffffffff1690565b600254610f559060401c67ffffffffffffffff166104fe565b67ffffffffffffffff821611610f6a57505f90565b610fb0907fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff6fffffffffffffffff00000000000000006002549260401b16911617600255565b5f90565b91610fca610fd2945167ffffffffffffffff1690565b90519261210c565b6110205761055e610feb835167ffffffffffffffff1690565b7fc1aea5f7000000000000000000000000000000000000000000000000000000005f5267ffffffffffffffff16600452602490565b60029150565b61055e9061103c855467ffffffffffffffff1690565b7feae35725000000000000000000000000000000000000000000000000000000005f5267ffffffffffffffff9081166004524260245216604452606490565b905061109c42916110976104fe885467ffffffffffffffff1690565b610c4e565b11155f610e00565b7f9b772277000000000000000000000000000000000000000000000000000000005f524260045267ffffffffffffffff9081166024521660445260645ffd5b7f574f4e61000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f59d119e3000000000000000000000000000000000000000000000000000000005f5260045ffd5b35610b5081610922565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610195570180359067ffffffffffffffff821161019557602001918160051b3603831361019557565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610195570180359067ffffffffffffffff82116101955760200191813603831361019557565b9015611223578061121f916111be565b9091565b611191565b90602082549182815201915f5260205f20905f5b8181106112495750505090565b825473ffffffffffffffffffffffffffffffffffffffff1684526020909301926001928301920161123c565b335f9081527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e0602052604090205460ff16156112ad57565b7fe2517d3f000000000000000000000000000000000000000000000000000000005f52336004527fbd893629a699470e4ec82a5715bb4981fdaacc5d0a728bf5f55b801d8f4ef10b60245260445ffd5b805f525f60205260ff6113313360405f209073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b54161561133b5750565b7fe2517d3f000000000000000000000000000000000000000000000000000000005f523360045260245260445ffd5b67ffffffffffffffff168061137c5750565b7f3ce598a9000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b6040519060e0820182811067ffffffffffffffff821117610a8e57604052606060c0838281528260208201525f60408201525f838201525f60808201528260a08201520152565b8051600110156112235760400190565b805160071015611223576101000190565b8051600d1015611223576101c00190565b8051600e1015611223576101e00190565b805160081015611223576101200190565b8051600310156112235760800190565b8051600b1015611223576101800190565b8051600c1015611223576101a00190565b8051600410156112235760a00190565b8051156112235760200190565b8051600210156112235760600190565b805160101015611223576102200190565b80518210156112235760209160051b010190565b67ffffffffffffffff8111610a8e5760051b60200190565b906114e8826114c6565b6114f56040519182610aaf565b828152601f1961150582946114c6565b0190602036910137565b90602082519201517fffffffffffffffffffffffffffffffffffffffff00000000000000000000000081169260148110611547575050565b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000929350829060140360031b1b161690565b60405160a0919061158a8382610aaf565b6004815291601f1901825f5b8281106115a257505050565b806060602080938501015201611596565b906115bd826114c6565b6115ca6040519182610aaf565b828152601f196115da82946114c6565b01905f5b8281106115ea57505050565b8060606020809385010152016115de565b61161461160f6116096113a7565b92612500565b61256f565b80825251600f8110611ae457507f1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934761165561164f83516113ee565b5161263a565b03611aa957600161166f61166983516113fe565b5161252d565b03611a6e577f63746963616c2062797a616e74696e65206661756c7420746f6c6572616e63656116a261164f835161140f565b03611a33576116ba6116b48251611420565b51612656565b80516008811490811591611a03575b506119c957506116f36116e26104fe6116698451611431565b67ffffffffffffffff166040830152565b61170061164f8251611442565b60608201526117296117186104fe6116698451611452565b67ffffffffffffffff166080830152565b61174161160f61173c6116b48451611463565b612500565b906020810191808352516005810361199e575061176761176183516113ee565b5161256f565b908151156119765761177982516114de565b9360a082019485525f5b8351811015611912576117996116b482866114b2565b8051601481036118e757506117b06117b69161150f565b60601c90565b73ffffffffffffffffffffffffffffffffffffffff811680156118a5575f5b8381106118115750509061180b6001926117f0838a516114b2565b9073ffffffffffffffffffffffffffffffffffffffff169052565b01611783565b8161185661183d611823848d516114b2565b5173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1690565b14611863576001016117d5565b7f41fe18cc000000000000000000000000000000000000000000000000000000005f5273ffffffffffffffffffffffffffffffffffffffff831660045260245ffd5b7f59bff387000000000000000000000000000000000000000000000000000000005f5273ffffffffffffffffffffffffffffffffffffffff821660045260245ffd5b7f83e46ad2000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b5092611761919450611925925051611474565b61192f81516115b3565b9260c081019384525f5b82518110156119705780611969816119566116b4600195886114b2565b88519061196383836114b2565b526114b2565b5001611939565b50925050565b7f339e1ffb000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f30c6792a000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b6119ff906040519182917fd5edd2a500000000000000000000000000000000000000000000000000000000835260048301610934565b0390fd5b7f011b4d03dd8c01f1049143cf9c4c817e4b167f1d1b83e5c6f0f10d89ba1e7bce9150602083012014155f6116c9565b611a4361164f61055e925161140f565b7fa19e609c000000000000000000000000000000000000000000000000000000005f52600452602490565b611a7e61166961055e92516113fe565b7ff71b722f000000000000000000000000000000000000000000000000000000005f52600452602490565b611ab961164f61055e92516113ee565b7fb8120dca000000000000000000000000000000000000000000000000000000005f52600452602490565b7fbc277732000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b67ffffffffffffffff1690815f52600460205260405f209167ffffffffffffffff83541615611b3b5750565b7ff761631b000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b611c03611b71611579565b611bea611b8860208501611b8e611b888251611484565b51612f48565b611b9785611484565b52611ba184611484565b50611baf611b8882516113ee565b611bb8856113ee565b52611bc2846113ee565b50611bd0611b888251611491565b611bd985611491565b52611be384611491565b5051611442565b611bf382611442565b52611bfd81611442565b50612680565b611c0e8251516115b3565b905f5b83518051821015611c64579080600192600c82145f14611c52575050611c3683612718565b611c4082866114b2565b52611c4b81856114b2565b5001611c11565b611c5f91611b88916114b2565b611c36565b505050611c719150612680565b6020815191012090565b919091611c8883516114de565b925f5b8151811015611e8157611c9e81836114b2565b51805160418103611e56575080601b60ff611ced611ce7611cc1611cfa966126f7565b517fff000000000000000000000000000000000000000000000000000000000000001690565b60f81c90565b1610611e03575b84613034565b90611d0481612846565b1590811591611df9575b508015611ddb575b611db35773ffffffffffffffffffffffffffffffffffffffff81165f5b838110611d5357505090611d4d6001926117f083896114b2565b01611c8b565b81611d6461183d611823848c6114b2565b14611d7157600101611d33565b7f33af0d5f000000000000000000000000000000000000000000000000000000005f5273ffffffffffffffffffffffffffffffffffffffff831660045260245ffd5b7f09cb44e6000000000000000000000000000000000000000000000000000000005f5260045ffd5b5073ffffffffffffffffffffffffffffffffffffffff811615611d16565b905015155f611d0e565b611e45611e1d611e18611ce7611cc1856126f7565b612834565b60f81b7fff000000000000000000000000000000000000000000000000000000000000001690565b5f1a611e50826126f7565b53611cf4565b7ff2db9ce1000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b505050565b5f198114610c495760010190565b905f915f5b8151811015611eed57611ecc73ffffffffffffffffffffffffffffffffffffffff611ec483856114b2565b511684612850565b611ed9575b600101611e99565b92611ee5600191611e86565b939050611ed1565b50506003611efc915404610c3b565b90818110611f08575050565b7fe2dcb1b9000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b905f198201918211610c4957565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408201918211610c4957565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808201918211610c4957565b6020039060208211610c4957565b91908203918211610c4957565b905f915f5b815181101561201257611ff173ffffffffffffffffffffffffffffffffffffffff611fe983856114b2565b5116846128af565b611ffe575b600101611fbe565b9261200a600191611e86565b939050611ff6565b50505190600382048203918211610c495781811061202e575050565b7f7818f4e4000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b6120a69261160f9261173c926040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000602082019260601b168252601481526104d7603482610aaf565b805160021015611223576060610b5091015161263a565b60206040818301928281528451809452019201905f5b8181106120e05750505090565b825173ffffffffffffffffffffffffffffffffffffffff168452602093840193909201916001016120d3565b919067ffffffffffffffff8084541691161490811591612172575b5061216c5760405161214c816104c96020820194602086526002604084019101611228565b51902090604051612165816104c96020820194856120bd565b5190201490565b50505f90565b9050600182015414155f612127565b805f525f60205260ff6121b58360405f209073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b541661216c57805f525f6020526121ed8260405f209073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905573ffffffffffffffffffffffffffffffffffffffff339216907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d5f80a4600190565b805f525f60205260ff61228c8360405f209073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b54161561216c57805f525f6020526122c58260405f209073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00815416905573ffffffffffffffffffffffffffffffffffffffff339216907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b5f80a4600190565b60208151910120604051602081019182527f1260944489272988d9df285149b5aa1b0f48f2136d6f416159f840a3e0747600604082015260408152612373606082610aaf565b51902090565b60405190612388602083610aaf565b5f808352366020840137565b9061239e82610ae3565b6123ab6040519182610aaf565b828152601f196115058294610ae3565b61160f6123fd919493946123cf6020610ae3565b956123dd6040519788610aaf565b602087526123eb6020610ae3565b601f1960208901910136823752612500565b906124088451610c5b565b9184511515806124e0575b61241c90612526565b61242e6124295f85611fac565b612394565b925f19015f5b818110612448575050610b50939450612a23565b806124ca600f61248d6124c4611ce7611cc18d61246760029960011c90565b908d6124be8a6124b68a61248d612484611ce7611cc18a8a612707565b60041c600f1690565b1660f81b7fff000000000000000000000000000000000000000000000000000000000000001690565b5f1a92612707565b53612707565b60ff1690565b5f1a6124d96001830188612707565b5301612434565b506001612413565b604051906124f582610a93565b5f6020838281520152565b6125086124e8565b5060208151916040519261251b84610a93565b835201602082015290565b1561019557565b80518015159081612563575b50156101955761254890612cf9565b90519060208110612557575090565b6020036101000a900490565b6021915011155f612539565b61257881612d25565b156101955761258681612d45565b61258f816114c6565b9161259d6040519384610aaf565b818352601f196125ac836114c6565b015f5b81811061262357505060206125cf9101516125c981612da6565b90610c4e565b5f905b8282106125df5750505090565b61261b816125ee600193612e0c565b906125f7610ad2565b82815281602082015261260a86896114b2565b5261261585886114b2565b50610c4e565b9101906125d2565b60209061262e6124e8565b828288010152016125af565b6021815103610195576020015160018101809111610c49575190565b80511561019557612669610b5091612cf9565b61267581939293612394565b928360200190612ed5565b5f9190825b81518410156126ae5761269884836114b2565b51518101809111610c4957600190930192612685565b6126b9919350612394565b5f9060205b84518310156126e9576001906126d484876114b2565b518051602082018386015e51019201916126be565b509050610b50919250612f74565b8051604010156112235760600190565b908151811015611223570160200190565b805160018114908161281c575b501561275857610b50602080926040519381859251918291018484015e81015f838201520301601f198101835282610aaf565b80516037811161278857806021916020604051946001830186526080830182870153018385015e82010160405290565b906021906127e56127e08460ff6fffffffffffffffffffffffffffffffff821160071b67ffffffffffffffff83821c1160061b1763ffffffff83821c1160051b1761ffff83821c1160041b17918260031c921c111790565b610c3b565b92604051938360208284019460018601885260b7840182890153848460031b610100031b8389015201918601015e82010160405290565b905015611223576080602082015160f81c105f612725565b60ff601b9116019060ff8211610c4957565b6004111561029457565b905f5b82548110156128a857825f5273ffffffffffffffffffffffffffffffffffffffff8160205f2001541673ffffffffffffffffffffffffffffffffffffffff8316146128a057600101612853565b505050600190565b5050505f90565b905f5b82518110156128a85773ffffffffffffffffffffffffffffffffffffffff6128da82856114b2565b511673ffffffffffffffffffffffffffffffffffffffff8316146128a0576001016128b2565b919061290c8351610c5b565b908351151580612a19575b61292090612526565b61292d6124298284611fac565b9381926001808416146129b7575b5f19869101935b848110612950575050505050565b836129ae60016129a4600f61248d6124c4611ce7611cc18b60029b61299d6129908861248d8f611ce7611cc16129896124849360011c90565b8099612707565b9b8d03809c5f1a92612707565b538c612707565b5f1a920189612707565b53018590612942565b92507f0f000000000000000000000000000000000000000000000000000000000000006129f66124c4611ce7611cc16129f08760011c90565b86612707565b60f81b165f1a612a0586611484565b535f19612a1183611e86565b93905061293b565b5081811115612917565b915f915f612a2f6124e8565b50845115612cc05790935f915b81518310156101955782158080612caa575b61019557159081612c8d575b5061019557612a6c61176183836114b2565b948551600281145f14612b695750612a8e612a896116b488611484565b6130c9565b95612aa4612a9d888884613136565b8092610c4e565b965111612b4b5715612adb5750612abb9051611f36565b11610195575111612ad2576116b4610b50916113ee565b50610b50612379565b919094612ae88651611f36565b82146101955780612b0a612b06612b006001946113ee565b51612d25565b1590565b15612b2c57612b1b612b21916113ee565b516130bb565b915b01919490612a3c565b612b38612b45916113ee565b5160208101519051902090565b91612b23565b505091509250612b5c915051611f36565b1161019557610b50612379565b929491939192601103612c2e5781518314612c1057612b9a612b946124c4611ce7611cc18787612707565b93610c3b565b92601081101561019557612bb7612bb182896114b2565b516130a5565b15612bd95750505050612bcc91925051611f36565b0361019557610b50612379565b86612bf1612b06612b0084600196989a97999b6114b2565b15612c0357612b4591612b1b916114b2565b612b4591612b38916114b2565b505050612c1d9051611f36565b03610195576116b4610b50916114a1565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c6964206e6f6465206c656e677468000000000000000000000000006044820152606490fd5b9050612ca2612c9c84846114b2565b5161306e565b14155f612a5a565b50612cb8612b3885856114b2565b871415612a4e565b509050612cf192507f56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421915014612526565b610b50612379565b906020820191612d098351612da6565b925190838201809211610c495751928303928311610c49579190565b805115612d4057602060c0910151515f1a10610fb057600190565b505f90565b805115612d40575f9060208101908151612d5e81612da6565b8101809111610c4957915190518101809111610c495791905b828110612d845750905090565b612d8d81612e0c565b8101809111610c4957612da09091611e86565b90612d77565b515f1a6080811015612db757505f90565b60b881108015612df6575b15612dcd5750600190565b60c0811015612de757610b50906127e09060b75b90611fac565b610b50906127e09060f7612de1565b5060c08110158015612dc2575060f88110612dc2565b80515f1a906080821015612e21575050600190565b60b8821015612e3757506127e0610b5091611f71565b60c0821015612e785760010151602082900360b7016101000a9004017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4a0190565b60f8821015612e8e57506127e0610b5091611f44565b60010151602082900360f7016101000a9004017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0a0190565b601f8111610c49576101000a90565b90918015611e81575b6020811015612f185780612ef157505050565b612f05612f00612f0a92611f9e565b612ec6565b611f36565b905182518216911916179052565b91908051825260208101809111610c49579060208101809111610c495791601f19810190811115612ede57610c0e565b612f528151612394565b90815115612f7057806020610b509201519051908360200190612ed5565b5090565b805190919060378111612fa6578060219160206040519560018301875260c0830182880153018386015e830101604052565b91602190612ffe6127e08560ff6fffffffffffffffffffffffffffffffff821160071b67ffffffffffffffff83821c1160061b1763ffffffff83821c1160051b1761ffff83821c1160041b17918260031c921c111790565b93604051948360208284019460018601895260f78401828a0153848460031b610100031b838a015201918701015e830101604052565b81519190604183036130645761305d9250602082015190606060408401519301515f1a906131da565b9192909190565b50505f9160029190565b80516020811015613086575060208101519051902090565b9060200151206040516020810191825260208152612373604082610aaf565b6001815103612d405760200151515f1a60801490565b6130c490612cf9565b902090565b9081511561019557600f6130e5612484611ce7611cc186611484565b16806130f85750610b5060025f93612900565b6001810361310d5750610b5060015f93612900565b600281036131235750610b506002600193612900565b60030361019557610b5060018093612900565b91905f5b838101808211610c495782518110806131d0575b156131c85761317e7fff000000000000000000000000000000000000000000000000000000000000009184612707565b51167fff000000000000000000000000000000000000000000000000000000000000006131ab8386612707565b511690036131c1576131bc90611e86565b61313a565b9250505090565b509250505090565b508351821061314e565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411613269579160209360809260ff5f9560405194855216868401526040830152606082015282805260015afa1561325e575f5173ffffffffffffffffffffffffffffffffffffffff81161561325457905f905f90565b505f906001905f90565b6040513d5f823e3d90fd5b5050505f916003919056fea164736f6c634300081c000a2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e06e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac47bd893629a699470e4ec82a5715bb4981fdaacc5d0a728bf5f55b801d8f4ef10bad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5"}} diff --git a/ibc-solidity/abi/bytecode/BesuQBFTLightClient.json b/ibc-solidity/abi/bytecode/BesuQBFTLightClient.json new file mode 100644 index 000000000..3b9952f83 --- /dev/null +++ b/ibc-solidity/abi/bytecode/BesuQBFTLightClient.json @@ -0,0 +1 @@ +{"abi":[{"type":"constructor","inputs":[{"name":"ibcRouter","type":"address","internalType":"address"},{"name":"initialTrustedHeight","type":"uint64","internalType":"uint64"},{"name":"initialTrustedTimestamp","type":"uint64","internalType":"uint64"},{"name":"initialTrustedStorageRoot","type":"bytes32","internalType":"bytes32"},{"name":"initialTrustedValidators","type":"address[]","internalType":"address[]"},{"name":"trustingPeriod","type":"uint64","internalType":"uint64"},{"name":"maxClockDrift","type":"uint64","internalType":"uint64"},{"name":"roleManager","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"DEFAULT_ADMIN_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"PROOF_SUBMITTER_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"getClientState","inputs":[],"outputs":[{"name":"","type":"bytes","internalType":"bytes"}],"stateMutability":"view"},{"type":"function","name":"getConsensusState","inputs":[{"name":"revisionHeight","type":"uint64","internalType":"uint64"}],"outputs":[{"name":"","type":"bytes","internalType":"bytes"}],"stateMutability":"view"},{"type":"function","name":"getRoleAdmin","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"grantRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"hasRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"misbehaviour","inputs":[{"name":"","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"view"},{"type":"function","name":"renounceRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"callerConfirmation","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"revokeRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"updateClient","inputs":[{"name":"updateMsg","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"","type":"uint8","internalType":"enum ILightClientMsgs.UpdateResult"}],"stateMutability":"nonpayable"},{"type":"function","name":"verifyMembership","inputs":[{"name":"msg_","type":"tuple","internalType":"struct ILightClientMsgs.MsgVerifyMembership","components":[{"name":"proof","type":"bytes","internalType":"bytes"},{"name":"proofHeight","type":"tuple","internalType":"struct IICS02ClientMsgs.Height","components":[{"name":"revisionNumber","type":"uint64","internalType":"uint64"},{"name":"revisionHeight","type":"uint64","internalType":"uint64"}]},{"name":"path","type":"bytes[]","internalType":"bytes[]"},{"name":"value","type":"bytes","internalType":"bytes"}]}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"verifyNonMembership","inputs":[{"name":"msg_","type":"tuple","internalType":"struct ILightClientMsgs.MsgVerifyNonMembership","components":[{"name":"proof","type":"bytes","internalType":"bytes"},{"name":"proofHeight","type":"tuple","internalType":"struct IICS02ClientMsgs.Height","components":[{"name":"revisionNumber","type":"uint64","internalType":"uint64"},{"name":"revisionHeight","type":"uint64","internalType":"uint64"}]},{"name":"path","type":"bytes[]","internalType":"bytes[]"}]}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"event","name":"RoleAdminChanged","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"previousAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"newAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"error","name":"AccessControlBadConfirmation","inputs":[]},{"type":"error","name":"AccessControlUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"},{"name":"neededRole","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"ConflictingConsensusState","inputs":[{"name":"revisionHeight","type":"uint64","internalType":"uint64"}]},{"type":"error","name":"ConsensusStateExpired","inputs":[{"name":"trustedTimestamp","type":"uint64","internalType":"uint64"},{"name":"currentTimestamp","type":"uint256","internalType":"uint256"},{"name":"trustingPeriod","type":"uint64","internalType":"uint64"}]},{"type":"error","name":"ConsensusStateNotFound","inputs":[{"name":"revisionHeight","type":"uint64","internalType":"uint64"}]},{"type":"error","name":"DuplicateCommitSealSigner","inputs":[{"name":"signer","type":"address","internalType":"address"}]},{"type":"error","name":"DuplicateValidator","inputs":[{"name":"validator","type":"address","internalType":"address"}]},{"type":"error","name":"EmptyValidatorSet","inputs":[]},{"type":"error","name":"HeaderFromFuture","inputs":[{"name":"currentTimestamp","type":"uint256","internalType":"uint256"},{"name":"headerTimestamp","type":"uint256","internalType":"uint256"},{"name":"maxClockDrift","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"InsufficientTrustedValidatorOverlap","inputs":[{"name":"actual","type":"uint256","internalType":"uint256"},{"name":"required","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"InsufficientValidatorQuorum","inputs":[{"name":"actual","type":"uint256","internalType":"uint256"},{"name":"required","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"InvalidCommitSeal","inputs":[]},{"type":"error","name":"InvalidCommitmentValue","inputs":[{"name":"expectedValue","type":"bytes32","internalType":"bytes32"},{"name":"actualValue","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"InvalidDifficulty","inputs":[{"name":"actualDifficulty","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"InvalidECDSASignatureLength","inputs":[{"name":"length","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"InvalidExtraDataFormat","inputs":[{"name":"itemsLength","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"InvalidHeaderFormat","inputs":[{"name":"itemsLength","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"InvalidHeaderHeight","inputs":[]},{"type":"error","name":"InvalidHeaderTimestamp","inputs":[]},{"type":"error","name":"InvalidMixHash","inputs":[{"name":"actualMixHash","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"InvalidNonce","inputs":[{"name":"actualNonce","type":"bytes","internalType":"bytes"}]},{"type":"error","name":"InvalidOmmersHash","inputs":[{"name":"actualOmmersHash","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"InvalidPathLength","inputs":[{"name":"expectedLength","type":"uint256","internalType":"uint256"},{"name":"actualLength","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"InvalidRevisionNumber","inputs":[{"name":"providedRevisionNumber","type":"uint64","internalType":"uint64"}]},{"type":"error","name":"InvalidValidatorAddress","inputs":[{"name":"validator","type":"address","internalType":"address"}]},{"type":"error","name":"InvalidValidatorAddressLength","inputs":[{"name":"length","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"InvalidValueLength","inputs":[{"name":"expectedLength","type":"uint256","internalType":"uint256"},{"name":"actualLength","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"UnsupportedMisbehaviour","inputs":[]},{"type":"error","name":"ValueExists","inputs":[{"name":"actualValue","type":"bytes32","internalType":"bytes32"}]}],"bytecode":{"object":"0x6080604052346103d85761394280380380610019816103dc565b928339810190610100818303126103d85761003381610401565b9061004060208201610415565b9061004d60408201610415565b92606082015191608081015160018060401b0381116103d85781019286601f850112156103d8578351966001600160401b03881161037f578760051b9460206100978188016103dc565b809a81520190602082978201019283116103d857602001905b8282106103c0575050506100c660a08301610415565b956100df60e06100d860c08601610415565b9401610401565b956001600160401b03169081156103b1576001600160401b03169283156103a257885115610393575f5b89518110156101bf576001600160a01b03610124828c610429565b511615610198575f5b81811061013d5750600101610109565b6001600160a01b0361014f828d610429565b51166001600160a01b03610163848e610429565b5116146101725760010161012d565b6001600160a01b03610184838d610429565b511663107f863360e21b5f5260045260245ffd5b6001600160a01b03906101ab908b610429565b51166359bff38760e01b5f5260045260245ffd5b5060408051979896978a979181016001600160401b0381118282101761037f576040525f81526020810190848252604051926080840198848a1060018060401b038b111761037f576040998a526001600160a01b031680855260208086018490526001600160401b03928316868c01819052878416606090970196909652600180546001600160a01b031916909217825592516002805495516fffffffffffffffff0000000000000000908d1b81169285166001600160801b03199788161792909217815560038054988d1b90921697909516909517959095179093555f948552600490529590922080546001600160401b031916949094178455830191909155925193910191831161037f5768010000000000000000831161037f578154838355808410610359575b50905f5260205f205f5b83811061033c57846001600160a01b0381166103235750610312610547565b505b6040516132d890816105ca8239f35b8061033061033692610451565b506104c7565b50610314565b82516001600160a01b0316818301556020909201916001016102f3565b825f528360205f2091820191015b81811061037457506102e9565b5f8155600101610367565b634e487b7160e01b5f52604160045260245ffd5b63339e1ffb60e01b5f5260045ffd5b63574f4e6160e01b5f5260045ffd5b6359d119e360e01b5f5260045ffd5b602080916103cd84610401565b8152019101906100b0565b5f80fd5b6040519190601f01601f191682016001600160401b0381118382101761037f57604052565b51906001600160a01b03821682036103d857565b51906001600160401b03821682036103d857565b805182101561043d5760209160051b010190565b634e487b7160e01b5f52603260045260245ffd5b6001600160a01b0381165f9081525f5160206139225f395f51905f52602052604090205460ff166104c2576001600160a01b03165f8181525f5160206139225f395f51905f5260205260408120805460ff191660011790553391905f5160206138a25f395f51905f528180a4600190565b505f90565b6001600160a01b0381165f9081525f5160206138c25f395f51905f52602052604090205460ff166104c2576001600160a01b03165f8181525f5160206138c25f395f51905f5260205260408120805460ff191660011790553391905f5160206139025f395f51905f52905f5160206138a25f395f51905f529080a4600190565b5f80525f5160206138c25f395f51905f526020525f5160206138e25f395f51905f525460ff166105c5575f8080525f5160206138c25f395f51905f526020525f5160206138e25f395f51905f52805460ff1916600117905533905f5160206139025f395f51905f525f5160206138a25f395f51905f528280a4600190565b5f9056fe60806040526004361015610011575f80fd5b5f3560e01c806301ffc9a7146100f45780630bece356146100ef578063248a9ca3146100ea5780632f2ff15d146100e557806336568abe146100e05780634d6d9ffb146100db5780635972185a146100d6578063682ed5f0146100d157806391d14854146100cc578063a217fddf146100c7578063d547741f146100c2578063ddba6537146100bd578063edce8bdc146100b85763ef913a4b146100b3575f80fd5b6109c8565b61095e565b61088b565b61085c565b610842565b6107f4565b6105e6565b6105ac565b6103ac565b610350565b61031a565b6102b5565b610217565b34610195576020600319360112610195576004357fffffffff00000000000000000000000000000000000000000000000000000000811680910361019557807f7965db0b000000000000000000000000000000000000000000000000000000006020921490811561016b575b506040519015158152f35b7f01ffc9a7000000000000000000000000000000000000000000000000000000009150145f610160565b5f80fd5b9060206003198301126101955760043567ffffffffffffffff811161019557826023820112156101955780600401359267ffffffffffffffff84116101955760248483010111610195576024019190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b346101955761028161022836610199565b5f80527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e06020527f6e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac475490919060ff161561029957610d17565b6040516003821015610294576020918152f35b6101ea565b6102a1611275565b610d17565b90816020910312610195573590565b346101955760206003193601126101955760206102df6004355f525f602052600160405f20015490565b604051908152f35b6003196040910112610195576004359060243573ffffffffffffffffffffffffffffffffffffffff811681036101955790565b346101955761034e61032b366102e7565b90610349610344825f525f602052600160405f20015490565b6112fd565b6121d8565b005b346101955761035e366102e7565b3373ffffffffffffffffffffffffffffffffffffffff8216036103845761034e916122af565b7f6697b232000000000000000000000000000000000000000000000000000000005f5260045ffd5b346101955760206003193601126101955760043567ffffffffffffffff8111610195578060040160806003198336030112610195575f80527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e060205260ff7f6e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac4754161561059f575b61044761044260248401611133565b61136a565b60648201916001610458848461113d565b90500361056157906104a96104966104a261049d61049661049061048961048460446104e09a01611133565b611b0f565b988761113d565b9061120f565b3691610aff565b612384565b92806111be565b906001840154906040516104d7816104c960208201948560209181520190565b03601f198101835282610aaf565b51902091612412565b805161051f5761051b61050b6104fe845467ffffffffffffffff1690565b67ffffffffffffffff1690565b6040519081529081906020820190565b0390f35b61053361052e61055e92612557565b612584565b7fd039601e000000000000000000000000000000000000000000000000000000005f52600452602490565b5ffd5b61055e61056e848461113d565b7f88b3170e000000000000000000000000000000000000000000000000000000005f52600160045260245250604490565b6105a7611275565b610433565b34610195575f6003193601126101955760206040517fbd893629a699470e4ec82a5715bb4981fdaacc5d0a728bf5f55b801d8f4ef10b8152f35b346101955760206003193601126101955760043567ffffffffffffffff8111610195578060040160a06003198336030112610195575f80527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e060205260ff7f6e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac475416156107e7575b61067c61044260248401611133565b6064820191600161068d848461113d565b90500361056157608481019060206106a583856111be565b9050036107a957906106f46104966106ed6106e56106de61049d6104966104906106d761048460446107149c01611133565b9b8b61113d565b94876111be565b8101906102a6565b94806111be565b906001850154906040516104d7816104c960208201948560209181520190565b8051156107755761052e61072791612557565b908082036107475761051b61050b6104fe855467ffffffffffffffff1690565b7f56ed1b63000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b61055e827f56ed1b63000000000000000000000000000000000000000000000000000000005f52906044916004525f602452565b61055e6107b683856111be565b7f24fadac8000000000000000000000000000000000000000000000000000000005f52602060045260245250604490565b6107ef611275565b61066d565b3461019557602060ff610836610809366102e7565b905f525f845260405f209073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b54166040519015158152f35b34610195575f6003193601126101955760206040515f8152f35b346101955761034e61086d366102e7565b90610886610344825f525f602052600160405f20015490565b6122af565b346101955761089936610199565b50505f80527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e06020527f6e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac475460ff1615610915575b7f2c1ed462000000000000000000000000000000000000000000000000000000005f5260045ffd5b61091d611275565b6108ed565b67ffffffffffffffff81160361019557565b601f19601f602060409481855280519182918282880152018686015e5f8582860101520116010190565b346101955760206003193601126101955761051b61098160043561048481610922565b6109bc67ffffffffffffffff8254166104c9600184015493604051948593602085015260408401526060808401526002608084019101611228565b60405191829182610934565b34610195575f6003193601126101955761051b60405173ffffffffffffffffffffffffffffffffffffffff60015416602082015267ffffffffffffffff600254818116604084015260401c16606082015267ffffffffffffffff600354818116608084015260401c1660a082015260a081526109bc60c082610aaf565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6060810190811067ffffffffffffffff821117610a8e57604052565b610a45565b6040810190811067ffffffffffffffff821117610a8e57604052565b90601f601f19910116810190811067ffffffffffffffff821117610a8e57604052565b60405190610ae1604083610aaf565b565b67ffffffffffffffff8111610a8e57601f01601f191660200190565b929192610b0b82610ae3565b91610b196040519384610aaf565b829481845281830111610195578281602093845f960137010152565b9080601f8301121561019557816020610b5093359101610aff565b90565b6020818303126101955780359067ffffffffffffffff8211610195570180820391608083126101955760405192610b8984610a72565b823567ffffffffffffffff811161019557604091610bac84601f19938701610b35565b8652011261019557604051610bc081610a93565b6020830135610bce81610922565b81526040830135610bde81610922565b60208201526020840152606082013567ffffffffffffffff811161019557610c069201610b35565b604082015290565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b9060018201809211610c4957565b610c0e565b91908201809211610c4957565b908160011b9180830460021490151715610c4957565b81519167ffffffffffffffff8311610a8e57680100000000000000008311610a8e578154838355808410610cf1575b506020610cb29101915f5260205f2090565b5f5b838110610cc15750505050565b6001906020610ce4855173ffffffffffffffffffffffffffffffffffffffff1690565b9401938184015501610cb4565b825f528360205f2091820191015b818110610d0c5750610ca0565b5f8155600101610cff565b610d2391810190610b53565b906020820191610d3f61044284515167ffffffffffffffff1690565b610d4981516115fb565b92604084019367ffffffffffffffff610d6a865167ffffffffffffffff1690565b161561110b576080810192610d8a6104fe855167ffffffffffffffff1690565b156110e3576003549267ffffffffffffffff604085901c16610dac8142610c4e565b865167ffffffffffffffff169081116110a45750505160200151610deb90610ddd9067ffffffffffffffff16611b0f565b9367ffffffffffffffff1690565b67ffffffffffffffff8116801515908161107b575b50611026575090610e6e91610e2f6002610e27610e1c85611ba1565b60c086015190611cd2565b950185611eeb565b610e3f60a0830194855190612010565b60406060610e6260015473ffffffffffffffffffffffffffffffffffffffff1690565b930151910151916120b3565b610e9b610e83865167ffffffffffffffff1690565b67ffffffffffffffff165f52600460205260405f2090565b610eb06104fe825467ffffffffffffffff1690565b610fb45750916002610f2e928694610f21610eec610edd610e83610f3c9a9b5167ffffffffffffffff1690565b955167ffffffffffffffff1690565b859067ffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000825416179055565b6001840155519101610c71565b5167ffffffffffffffff1690565b600254610f559060401c67ffffffffffffffff166104fe565b67ffffffffffffffff821611610f6a57505f90565b610fb0907fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff6fffffffffffffffff00000000000000006002549260401b16911617600255565b5f90565b91610fca610fd2945167ffffffffffffffff1690565b905192612163565b6110205761055e610feb835167ffffffffffffffff1690565b7fc1aea5f7000000000000000000000000000000000000000000000000000000005f5267ffffffffffffffff16600452602490565b60029150565b61055e9061103c855467ffffffffffffffff1690565b7feae35725000000000000000000000000000000000000000000000000000000005f5267ffffffffffffffff9081166004524260245216604452606490565b905061109c42916110976104fe885467ffffffffffffffff1690565b610c4e565b11155f610e00565b7f9b772277000000000000000000000000000000000000000000000000000000005f524260045267ffffffffffffffff9081166024521660445260645ffd5b7f574f4e61000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f59d119e3000000000000000000000000000000000000000000000000000000005f5260045ffd5b35610b5081610922565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610195570180359067ffffffffffffffff821161019557602001918160051b3603831361019557565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610195570180359067ffffffffffffffff82116101955760200191813603831361019557565b9015611223578061121f916111be565b9091565b611191565b90602082549182815201915f5260205f20905f5b8181106112495750505090565b825473ffffffffffffffffffffffffffffffffffffffff1684526020909301926001928301920161123c565b335f9081527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e0602052604090205460ff16156112ad57565b7fe2517d3f000000000000000000000000000000000000000000000000000000005f52336004527fbd893629a699470e4ec82a5715bb4981fdaacc5d0a728bf5f55b801d8f4ef10b60245260445ffd5b805f525f60205260ff6113313360405f209073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b54161561133b5750565b7fe2517d3f000000000000000000000000000000000000000000000000000000005f523360045260245260445ffd5b67ffffffffffffffff168061137c5750565b7f3ce598a9000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b6040519060e0820182811067ffffffffffffffff821117610a8e57604052606060c0838281528260208201525f60408201525f838201525f60808201528260a08201520152565b8051600110156112235760400190565b805160071015611223576101000190565b8051600d1015611223576101c00190565b8051600e1015611223576101e00190565b805160081015611223576101200190565b8051600310156112235760800190565b8051600b1015611223576101800190565b8051600c1015611223576101a00190565b8051600410156112235760a00190565b8051156112235760200190565b8051600210156112235760600190565b805160101015611223576102200190565b80518210156112235760209160051b010190565b67ffffffffffffffff8111610a8e5760051b60200190565b906114e8826114c6565b6114f56040519182610aaf565b828152601f1961150582946114c6565b0190602036910137565b90602082519201517fffffffffffffffffffffffffffffffffffffffff00000000000000000000000081169260148110611547575050565b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000929350829060140360031b1b161690565b60405160c0919061158a8382610aaf565b6005815291601f1901825f5b8281106115a257505050565b806060602080938501015201611596565b906115bd826114c6565b6115ca6040519182610aaf565b828152601f196115da82946114c6565b01905f5b8281106115ea57505050565b8060606020809385010152016115de565b61161461160f6116096113a7565b92612557565b6125c6565b80825251600f8110611ae457507f1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934761165561164f83516113ee565b51612691565b03611aa957600161166f61166983516113fe565b51612584565b03611a6e577f63746963616c2062797a616e74696e65206661756c7420746f6c6572616e63656116a261164f835161140f565b03611a33576116ba6116b48251611420565b516126ad565b80516008811490811591611a03575b506119c957506116f36116e26104fe6116698451611431565b67ffffffffffffffff166040830152565b61170061164f8251611442565b60608201526117296117186104fe6116698451611452565b67ffffffffffffffff166080830152565b61174161160f61173c6116b48451611463565b612557565b906020810191808352516005810361199e575061176761176183516113ee565b516125c6565b908151156119765761177982516114de565b9360a082019485525f5b8351811015611912576117996116b482866114b2565b8051601481036118e757506117b06117b69161150f565b60601c90565b73ffffffffffffffffffffffffffffffffffffffff811680156118a5575f5b8381106118115750509061180b6001926117f0838a516114b2565b9073ffffffffffffffffffffffffffffffffffffffff169052565b01611783565b8161185661183d611823848d516114b2565b5173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1690565b14611863576001016117d5565b7f41fe18cc000000000000000000000000000000000000000000000000000000005f5273ffffffffffffffffffffffffffffffffffffffff831660045260245ffd5b7f59bff387000000000000000000000000000000000000000000000000000000005f5273ffffffffffffffffffffffffffffffffffffffff821660045260245ffd5b7f83e46ad2000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b5092611761919450611925925051611474565b61192f81516115b3565b9260c081019384525f5b82518110156119705780611969816119566116b4600195886114b2565b88519061196383836114b2565b526114b2565b5001611939565b50925050565b7f339e1ffb000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f30c6792a000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b6119ff906040519182917fd5edd2a500000000000000000000000000000000000000000000000000000000835260048301610934565b0390fd5b7f011b4d03dd8c01f1049143cf9c4c817e4b167f1d1b83e5c6f0f10d89ba1e7bce9150602083012014155f6116c9565b611a4361164f61055e925161140f565b7fa19e609c000000000000000000000000000000000000000000000000000000005f52600452602490565b611a7e61166961055e92516113fe565b7ff71b722f000000000000000000000000000000000000000000000000000000005f52600452602490565b611ab961164f61055e92516113ee565b7fb8120dca000000000000000000000000000000000000000000000000000000005f52600452602490565b7fbc277732000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b67ffffffffffffffff1690815f52600460205260405f209167ffffffffffffffff83541615611b3b5750565b7ff761631b000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b60405190611b75604083610aaf565b600182527fc0000000000000000000000000000000000000000000000000000000000000006020830152565b611c5a611bac611579565b611c25611bc360208501611bc9611bc38251611484565b51612f9f565b611bd285611484565b52611bdc84611484565b50611bea611bc382516113ee565b611bf3856113ee565b52611bfd846113ee565b50611c0b611bc38251611491565b611c1485611491565b52611c1e84611491565b5051611442565b611c2e82611442565b52611c3881611442565b50611c41611b66565b611c4a82611474565b52611c5481611474565b506126d7565b611c658251516115b3565b905f5b83518051821015611cbb579080600192600c82145f14611ca9575050611c8d8361276f565b611c9782866114b2565b52611ca281856114b2565b5001611c68565b611cb691611bc3916114b2565b611c8d565b505050611cc891506126d7565b6020815191012090565b919091611cdf83516114de565b925f5b8151811015611ed857611cf581836114b2565b51805160418103611ead575080601b60ff611d44611d3e611d18611d519661274e565b517fff000000000000000000000000000000000000000000000000000000000000001690565b60f81c90565b1610611e5a575b8461308b565b90611d5b8161289d565b1590811591611e50575b508015611e32575b611e0a5773ffffffffffffffffffffffffffffffffffffffff81165f5b838110611daa57505090611da46001926117f083896114b2565b01611ce2565b81611dbb61183d611823848c6114b2565b14611dc857600101611d8a565b7f33af0d5f000000000000000000000000000000000000000000000000000000005f5273ffffffffffffffffffffffffffffffffffffffff831660045260245ffd5b7f09cb44e6000000000000000000000000000000000000000000000000000000005f5260045ffd5b5073ffffffffffffffffffffffffffffffffffffffff811615611d6d565b905015155f611d65565b611e9c611e74611e6f611d3e611d188561274e565b61288b565b60f81b7fff000000000000000000000000000000000000000000000000000000000000001690565b5f1a611ea78261274e565b53611d4b565b7ff2db9ce1000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b505050565b5f198114610c495760010190565b905f915f5b8151811015611f4457611f2373ffffffffffffffffffffffffffffffffffffffff611f1b83856114b2565b5116846128a7565b611f30575b600101611ef0565b92611f3c600191611edd565b939050611f28565b50506003611f53915404610c3b565b90818110611f5f575050565b7fe2dcb1b9000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b905f198201918211610c4957565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408201918211610c4957565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808201918211610c4957565b6020039060208211610c4957565b91908203918211610c4957565b905f915f5b81518110156120695761204873ffffffffffffffffffffffffffffffffffffffff61204083856114b2565b511684612906565b612055575b600101612015565b92612061600191611edd565b93905061204d565b50505190600382048203918211610c4957818110612085575050565b7f7818f4e4000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b6120fd9261160f9261173c926040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000602082019260601b168252601481526104d7603482610aaf565b805160021015611223576060610b50910151612691565b60206040818301928281528451809452019201905f5b8181106121375750505090565b825173ffffffffffffffffffffffffffffffffffffffff1684526020938401939092019160010161212a565b919067ffffffffffffffff80845416911614908115916121c9575b506121c3576040516121a3816104c96020820194602086526002604084019101611228565b519020906040516121bc816104c9602082019485612114565b5190201490565b50505f90565b9050600182015414155f61217e565b805f525f60205260ff61220c8360405f209073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b54166121c357805f525f6020526122448260405f209073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905573ffffffffffffffffffffffffffffffffffffffff339216907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d5f80a4600190565b805f525f60205260ff6122e38360405f209073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b5416156121c357805f525f60205261231c8260405f209073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00815416905573ffffffffffffffffffffffffffffffffffffffff339216907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b5f80a4600190565b60208151910120604051602081019182527f1260944489272988d9df285149b5aa1b0f48f2136d6f416159f840a3e07476006040820152604081526123ca606082610aaf565b51902090565b604051906123df602083610aaf565b5f808352366020840137565b906123f582610ae3565b6124026040519182610aaf565b828152601f196115058294610ae3565b61160f612454919493946124266020610ae3565b956124346040519788610aaf565b602087526124426020610ae3565b601f1960208901910136823752612557565b9061245f8451610c5b565b918451151580612537575b6124739061257d565b6124856124805f85612003565b6123eb565b925f19015f5b81811061249f575050610b50939450612a7a565b80612521600f6124e461251b611d3e611d188d6124be60029960011c90565b908d6125158a61250d8a6124e46124db611d3e611d188a8a61275e565b60041c600f1690565b1660f81b7fff000000000000000000000000000000000000000000000000000000000000001690565b5f1a9261275e565b5361275e565b60ff1690565b5f1a612530600183018861275e565b530161248b565b50600161246a565b6040519061254c82610a93565b5f6020838281520152565b61255f61253f565b5060208151916040519261257284610a93565b835201602082015290565b1561019557565b805180151590816125ba575b50156101955761259f90612d50565b905190602081106125ae575090565b6020036101000a900490565b6021915011155f612590565b6125cf81612d7c565b15610195576125dd81612d9c565b6125e6816114c6565b916125f46040519384610aaf565b818352601f19612603836114c6565b015f5b81811061267a575050602061262691015161262081612dfd565b90610c4e565b5f905b8282106126365750505090565b61267281612645600193612e63565b9061264e610ad2565b82815281602082015261266186896114b2565b5261266c85886114b2565b50610c4e565b910190612629565b60209061268561253f565b82828801015201612606565b6021815103610195576020015160018101809111610c49575190565b805115610195576126c0610b5091612d50565b6126cc819392936123eb565b928360200190612f2c565b5f9190825b8151841015612705576126ef84836114b2565b51518101809111610c49576001909301926126dc565b6127109193506123eb565b5f9060205b84518310156127405760019061272b84876114b2565b518051602082018386015e5101920191612715565b509050610b50919250612fcb565b8051604010156112235760600190565b908151811015611223570160200190565b8051600181149081612873575b50156127af57610b50602080926040519381859251918291018484015e81015f838201520301601f198101835282610aaf565b8051603781116127df57806021916020604051946001830186526080830182870153018385015e82010160405290565b9060219061283c6128378460ff6fffffffffffffffffffffffffffffffff821160071b67ffffffffffffffff83821c1160061b1763ffffffff83821c1160051b1761ffff83821c1160041b17918260031c921c111790565b610c3b565b92604051938360208284019460018601885260b7840182890153848460031b610100031b8389015201918601015e82010160405290565b905015611223576080602082015160f81c105f61277c565b60ff601b9116019060ff8211610c4957565b6004111561029457565b905f5b82548110156128ff57825f5273ffffffffffffffffffffffffffffffffffffffff8160205f2001541673ffffffffffffffffffffffffffffffffffffffff8316146128f7576001016128aa565b505050600190565b5050505f90565b905f5b82518110156128ff5773ffffffffffffffffffffffffffffffffffffffff61293182856114b2565b511673ffffffffffffffffffffffffffffffffffffffff8316146128f757600101612909565b91906129638351610c5b565b908351151580612a70575b6129779061257d565b6129846124808284612003565b938192600180841614612a0e575b5f19869101935b8481106129a7575050505050565b83612a0560016129fb600f6124e461251b611d3e611d188b60029b6129f46129e7886124e48f611d3e611d186129e06124db9360011c90565b809961275e565b9b8d03809c5f1a9261275e565b538c61275e565b5f1a92018961275e565b53018590612999565b92507f0f00000000000000000000000000000000000000000000000000000000000000612a4d61251b611d3e611d18612a478760011c90565b8661275e565b60f81b165f1a612a5c86611484565b535f19612a6883611edd565b939050612992565b508181111561296e565b915f915f612a8661253f565b50845115612d175790935f915b81518310156101955782158080612d01575b61019557159081612ce4575b5061019557612ac361176183836114b2565b948551600281145f14612bc05750612ae5612ae06116b488611484565b613120565b95612afb612af488888461318d565b8092610c4e565b965111612ba25715612b325750612b129051611f8d565b11610195575111612b29576116b4610b50916113ee565b50610b506123d0565b919094612b3f8651611f8d565b82146101955780612b61612b5d612b576001946113ee565b51612d7c565b1590565b15612b8357612b72612b78916113ee565b51613112565b915b01919490612a93565b612b8f612b9c916113ee565b5160208101519051902090565b91612b7a565b505091509250612bb3915051611f8d565b1161019557610b506123d0565b929491939192601103612c855781518314612c6757612bf1612beb61251b611d3e611d18878761275e565b93610c3b565b92601081101561019557612c0e612c0882896114b2565b516130fc565b15612c305750505050612c2391925051611f8d565b0361019557610b506123d0565b86612c48612b5d612b5784600196989a97999b6114b2565b15612c5a57612b9c91612b72916114b2565b612b9c91612b8f916114b2565b505050612c749051611f8d565b03610195576116b4610b50916114a1565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c6964206e6f6465206c656e677468000000000000000000000000006044820152606490fd5b9050612cf9612cf384846114b2565b516130c5565b14155f612ab1565b50612d0f612b8f85856114b2565b871415612aa5565b509050612d4892507f56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42191501461257d565b610b506123d0565b906020820191612d608351612dfd565b925190838201809211610c495751928303928311610c49579190565b805115612d9757602060c0910151515f1a10610fb057600190565b505f90565b805115612d97575f9060208101908151612db581612dfd565b8101809111610c4957915190518101809111610c495791905b828110612ddb5750905090565b612de481612e63565b8101809111610c4957612df79091611edd565b90612dce565b515f1a6080811015612e0e57505f90565b60b881108015612e4d575b15612e245750600190565b60c0811015612e3e57610b50906128379060b75b90612003565b610b50906128379060f7612e38565b5060c08110158015612e19575060f88110612e19565b80515f1a906080821015612e78575050600190565b60b8821015612e8e5750612837610b5091611fc8565b60c0821015612ecf5760010151602082900360b7016101000a9004017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4a0190565b60f8821015612ee55750612837610b5091611f9b565b60010151602082900360f7016101000a9004017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0a0190565b601f8111610c49576101000a90565b90918015611ed8575b6020811015612f6f5780612f4857505050565b612f5c612f57612f6192611ff5565b612f1d565b611f8d565b905182518216911916179052565b91908051825260208101809111610c49579060208101809111610c495791601f19810190811115612f3557610c0e565b612fa981516123eb565b90815115612fc757806020610b509201519051908360200190612f2c565b5090565b805190919060378111612ffd578060219160206040519560018301875260c0830182880153018386015e830101604052565b916021906130556128378560ff6fffffffffffffffffffffffffffffffff821160071b67ffffffffffffffff83821c1160061b1763ffffffff83821c1160051b1761ffff83821c1160041b17918260031c921c111790565b93604051948360208284019460018601895260f78401828a0153848460031b610100031b838a015201918701015e830101604052565b81519190604183036130bb576130b49250602082015190606060408401519301515f1a90613231565b9192909190565b50505f9160029190565b805160208110156130dd575060208101519051902090565b90602001512060405160208101918252602081526123ca604082610aaf565b6001815103612d975760200151515f1a60801490565b61311b90612d50565b902090565b9081511561019557600f61313c6124db611d3e611d1886611484565b168061314f5750610b5060025f93612957565b600181036131645750610b5060015f93612957565b6002810361317a5750610b506002600193612957565b60030361019557610b5060018093612957565b91905f5b838101808211610c49578251811080613227575b1561321f576131d57fff00000000000000000000000000000000000000000000000000000000000000918461275e565b51167fff00000000000000000000000000000000000000000000000000000000000000613202838661275e565b511690036132185761321390611edd565b613191565b9250505090565b509250505090565b50835182106131a5565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084116132c0579160209360809260ff5f9560405194855216868401526040830152606082015282805260015afa156132b5575f5173ffffffffffffffffffffffffffffffffffffffff8116156132ab57905f905f90565b505f906001905f90565b6040513d5f823e3d90fd5b5050505f916003919056fea164736f6c634300081c000a2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e06e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac47bd893629a699470e4ec82a5715bb4981fdaacc5d0a728bf5f55b801d8f4ef10bad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5"}} diff --git a/ibc-solidity/abi/bytecode/CosmosIFTSendCallConstructor.json b/ibc-solidity/abi/bytecode/CosmosIFTSendCallConstructor.json deleted file mode 100644 index a4369292e..000000000 --- a/ibc-solidity/abi/bytecode/CosmosIFTSendCallConstructor.json +++ /dev/null @@ -1 +0,0 @@ -{"abi":[{"type":"constructor","inputs":[{"name":"bridgeReceiveTypeUrl_","type":"string","internalType":"string"},{"name":"denom_","type":"string","internalType":"string"},{"name":"icaAddress_","type":"string","internalType":"string"}],"stateMutability":"nonpayable"},{"type":"function","name":"bridgeReceiveTypeUrl","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"constructMintCall","inputs":[{"name":"receiver","type":"string","internalType":"string"},{"name":"amount","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bytes","internalType":"bytes"}],"stateMutability":"view"},{"type":"function","name":"denom","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"icaAddress","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"}],"bytecode":{"object":"0x60806040523461046857610ecb803803806100198161046c565b92833981016060828203126104685781516001600160401b0381116104685781610044918401610491565b60208301519092906001600160401b0381116104685782610066918301610491565b60408201519092906001600160401b038111610468576100869201610491565b82516001600160401b0381116102a3575f54600181811c9116801561045e575b602082101461028557601f81116103fc575b506020601f821160011461039b57819293945f92610390575b50508160011b915f199060031b1c1916175f555b81516001600160401b0381116102a357600154600181811c91168015610386575b602082101461028557601f8111610323575b50602092601f82116001146102c257928192935f926102b7575b50508160011b915f199060031b1c1916176001555b80516001600160401b0381116102a357600254600181811c91168015610299575b602082101461028557601f8111610222575b50602091601f82116001146101c2579181925f926101b7575b50508160011b915f199060031b1c1916176002555b6040516109e890816104e38239f35b015190505f80610193565b601f1982169260025f52805f20915f5b85811061020a575083600195106101f2575b505050811b016002556101a8565b01515f1960f88460031b161c191690555f80806101e4565b919260206001819286850151815501940192016101d2565b60025f527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace601f830160051c8101916020841061027b575b601f0160051c01905b818110610270575061017a565b5f8155600101610263565b909150819061025a565b634e487b7160e01b5f52602260045260245ffd5b90607f1690610168565b634e487b7160e01b5f52604160045260245ffd5b015190505f80610132565b601f1982169360015f52805f20915f5b86811061030b57508360019596106102f3575b505050811b01600155610147565b01515f1960f88460031b161c191690555f80806102e5565b919260206001819286850151815501940192016102d2565b60015f527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6601f830160051c8101916020841061037c575b601f0160051c01905b8181106103715750610118565b5f8155600101610364565b909150819061035b565b90607f1690610106565b015190505f806100d1565b601f198216905f8052805f20915f5b8181106103e4575095836001959697106103cc575b505050811b015f556100e5565b01515f1960f88460031b161c191690555f80806103bf565b9192602060018192868b0151815501940192016103aa565b5f80527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563601f830160051c81019160208410610454575b601f0160051c01905b81811061044957506100b8565b5f815560010161043c565b9091508190610433565b90607f16906100a6565b5f80fd5b6040519190601f01601f191682016001600160401b038111838210176102a357604052565b81601f82011215610468578051906001600160401b0382116102a3576104c0601f8301601f191660200161046c565b928284526020838301011161046857815f9260208093018386015e830101529056fe60806040526004361015610011575f80fd5b5f3560e01c80632ff02e27146107dc57806356d981a7146102275780638f2edc84146101675763c370b04214610045575f80fd5b34610163575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610163576040515f6001546100838161089f565b808452906001811690811561012157506001146100c3575b6100bf836100ab818503826108f0565b60405191829160208352602083019061095e565b0390f35b60015f9081527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6939250905b808210610107575090915081016020016100ab61009b565b9192600181602092548385880101520191019092916100ef565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660208086019190915291151560051b840190910191506100ab905061009b565b5f80fd5b34610163575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610163576040515f5f546101a48161089f565b808452906001811690811561012157506001146101cb576100bf836100ab818503826108f0565b5f8080527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563939250905b80821061020d575090915081016020016100ab61009b565b9192600181602092548385880101520191019092916101f5565b346101635760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101635760043567ffffffffffffffff8111610163573660238201121561016357806004013567ffffffffffffffff8111610163573660248284010111610163575f602435807a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008110156107b4575b806d04ee2d6d415b85acef8100000000600a921015610799575b662386f26fc10000811015610785575b6305f5e100811015610774575b612710811015610765575b6064811015610757575b101561074d575b6001820190600a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602161035b610345866109a1565b9561035360405197886108f0565b8087526109a1565b957fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06020870197013688378501015b01917f30313233343536373839616263646566000000000000000000000000000000008282061a83530480156103e4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600a919261038a565b5050604051927f7b226d65737361676573223a5b7b224074797065223a2200000000000000000060208501525f945f5461041d8161089f565b906001811690811561071257506001146106bc575b507f222c227369676e6572223a22000000000000000000000000000000000000000086526002545f966104648261089f565b916001811690811561067e5750600114610625575b50507f222c2264656e6f6d223a2200000000000000000000000000000000000000000086525f956001546104ac8161089f565b90600181169081156105e25750600114610584575b5050600e6100ab946004948489600c9660248b977f222c227265636569766572223a220000000000000000000000000000000000006100bf9e52018683013701907f222c22616d6f756e74223a22000000000000000000000000000000000000000084830152518092601a83015e01017f227d5d7d000000000000000000000000000000000000000000000000000000008382015203017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe48101845201826108f0565b60015f908152919750907fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65b8282106105cb57505095909501600b0194600e6100ab6104c1565b60018160209254600b858d010152019101906105b0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600b84810191909152821515909202909201019650600e90506100ab6104c1565b60025f90815292975090917f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace5b83821061066757505001600c01948680610479565b60018160209254600c858701015201910190610652565b600c9499507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091509291921683830152801515020101948680610479565b5f808052919650907f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5635b8282106106fb57505084016037019486610432565b600181602092546037858b010152019101906106e6565b60379398507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682870152801515028501019486610432565b906001019061030f565b606460029104930192610308565b612710600491049301926102fe565b6305f5e100600891049301926102f3565b662386f26fc10000601091049301926102e6565b6d04ee2d6d415b85acef8100000000602091049301926102d6565b50604091507a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000081046102bc565b34610163575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610163576040515f60025461081a8161089f565b80845290600181169081156101215750600114610841576100bf836100ab818503826108f0565b60025f9081527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace939250905b808210610885575090915081016020016100ab61009b565b91926001816020925483858801015201910190929161086d565b90600182811c921680156108e6575b60208310146108b957565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b91607f16916108ae565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761093157604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602080948051918291828752018686015e5f8582860101520116010190565b67ffffffffffffffff811161093157601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0166020019056fea164736f6c634300081c000a","sourceMap":"462:1821:57:-:0;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;-1:-1:-1;;;;;462:1821:57;;;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;;;;;462:1821:57;;;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;;;;;462:1821:57;;;;;;;;:::i;:::-;;;-1:-1:-1;;;;;462:1821:57;;;;-1:-1:-1;462:1821:57;;;;;;;;;;;-1:-1:-1;462:1821:57;;;;;;;;;;;-1:-1:-1;462:1821:57;;;;;;;;;;;;;-1:-1:-1;462:1821:57;;;;;;;;;;;;;;;;;;;-1:-1:-1;462:1821:57;;;;-1:-1:-1;;;;;462:1821:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;462:1821:57;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;462:1821:57;;;;1624:24;462:1821;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;462:1821:57;;;;;;;;;;;;;;;;;;;1624:24;462:1821;;;;;;;;;;;;;;;-1:-1:-1;462:1821:57;;;;;;;;;;1624:24;-1:-1:-1;462:1821:57;;-1:-1:-1;462:1821:57;;-1:-1:-1;462:1821:57;;;;;;;;;;;;;;;;;;;;1624:24;462:1821;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1624:24;-1:-1:-1;462:1821:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;462:1821:57;;;;;;;;;-1:-1:-1;462:1821:57;;;;;;;;-1:-1:-1;462:1821:57;;;;;-1:-1:-1;462:1821:57;;;;;;;;;;;;-1:-1:-1;462:1821:57;;;;;-1:-1:-1;462:1821:57;;;;;-1:-1:-1;462:1821:57;;;;;;;;;;;-1:-1:-1;462:1821:57;;-1:-1:-1;462:1821:57;;-1:-1:-1;462:1821:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;462:1821:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;462:1821:57;;;;;;;;;-1:-1:-1;462:1821:57;;;;;;;;;;;;;;;-1:-1:-1;462:1821:57;;;;;;;;;;-1:-1:-1;462:1821:57;;;-1:-1:-1;462:1821:57;;-1:-1:-1;462:1821:57;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;462:1821:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;462:1821:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;462:1821:57;;;;;;;;;-1:-1:-1;462:1821:57;;;;;;;;;;;;-1:-1:-1;462:1821:57;;;;;;;;;-1:-1:-1;;462:1821:57;;;-1:-1:-1;;;;;462:1821:57;;;;;;;;;;:::o;:::-;;;;;;;;;;;;-1:-1:-1;;;;;462:1821:57;;;;;;;;-1:-1:-1;;462:1821:57;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;462:1821:57;;;;;;;;;;;;;;:::o","linkReferences":{}},"deployedBytecode":{"object":"0x60806040526004361015610011575f80fd5b5f3560e01c80632ff02e27146107dc57806356d981a7146102275780638f2edc84146101675763c370b04214610045575f80fd5b34610163575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610163576040515f6001546100838161089f565b808452906001811690811561012157506001146100c3575b6100bf836100ab818503826108f0565b60405191829160208352602083019061095e565b0390f35b60015f9081527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6939250905b808210610107575090915081016020016100ab61009b565b9192600181602092548385880101520191019092916100ef565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660208086019190915291151560051b840190910191506100ab905061009b565b5f80fd5b34610163575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610163576040515f5f546101a48161089f565b808452906001811690811561012157506001146101cb576100bf836100ab818503826108f0565b5f8080527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563939250905b80821061020d575090915081016020016100ab61009b565b9192600181602092548385880101520191019092916101f5565b346101635760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101635760043567ffffffffffffffff8111610163573660238201121561016357806004013567ffffffffffffffff8111610163573660248284010111610163575f602435807a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008110156107b4575b806d04ee2d6d415b85acef8100000000600a921015610799575b662386f26fc10000811015610785575b6305f5e100811015610774575b612710811015610765575b6064811015610757575b101561074d575b6001820190600a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602161035b610345866109a1565b9561035360405197886108f0565b8087526109a1565b957fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06020870197013688378501015b01917f30313233343536373839616263646566000000000000000000000000000000008282061a83530480156103e4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600a919261038a565b5050604051927f7b226d65737361676573223a5b7b224074797065223a2200000000000000000060208501525f945f5461041d8161089f565b906001811690811561071257506001146106bc575b507f222c227369676e6572223a22000000000000000000000000000000000000000086526002545f966104648261089f565b916001811690811561067e5750600114610625575b50507f222c2264656e6f6d223a2200000000000000000000000000000000000000000086525f956001546104ac8161089f565b90600181169081156105e25750600114610584575b5050600e6100ab946004948489600c9660248b977f222c227265636569766572223a220000000000000000000000000000000000006100bf9e52018683013701907f222c22616d6f756e74223a22000000000000000000000000000000000000000084830152518092601a83015e01017f227d5d7d000000000000000000000000000000000000000000000000000000008382015203017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe48101845201826108f0565b60015f908152919750907fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65b8282106105cb57505095909501600b0194600e6100ab6104c1565b60018160209254600b858d010152019101906105b0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600b84810191909152821515909202909201019650600e90506100ab6104c1565b60025f90815292975090917f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace5b83821061066757505001600c01948680610479565b60018160209254600c858701015201910190610652565b600c9499507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091509291921683830152801515020101948680610479565b5f808052919650907f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5635b8282106106fb57505084016037019486610432565b600181602092546037858b010152019101906106e6565b60379398507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682870152801515028501019486610432565b906001019061030f565b606460029104930192610308565b612710600491049301926102fe565b6305f5e100600891049301926102f3565b662386f26fc10000601091049301926102e6565b6d04ee2d6d415b85acef8100000000602091049301926102d6565b50604091507a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000081046102bc565b34610163575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610163576040515f60025461081a8161089f565b80845290600181169081156101215750600114610841576100bf836100ab818503826108f0565b60025f9081527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace939250905b808210610885575090915081016020016100ab61009b565b91926001816020925483858801015201910190929161086d565b90600182811c921680156108e6575b60208310146108b957565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b91607f16916108ae565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761093157604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602080948051918291828752018686015e5f8582860101520116010190565b67ffffffffffffffff811161093157601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0166020019056fea164736f6c634300081c000a","sourceMap":"462:1821:57:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;842:19;462:1821;;;;:::i;:::-;;;;;842:19;462:1821;;;842:19;;;;462:1821;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;842:19;462:1821;;;;;;;-1:-1:-1;462:1821:57;;;;;;;-1:-1:-1;462:1821:57;;-1:-1:-1;462:1821:57;;;;;;;;;;842:19;462:1821;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;462:1821:57;;-1:-1:-1;462:1821:57;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;462:1821:57;;;;;;;-1:-1:-1;462:1821:57;;-1:-1:-1;462:1821:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29291:8:123;29282:17;;;29278:103;;462:1821:57;29398:17:123;29407:8;29978:7;29398:17;;;29394:103;;462:1821:57;29523:8:123;29514:17;;;29510:103;;462:1821:57;29639:7:123;29630:16;;;29626:100;;462:1821:57;29752:7:123;29743:16;;;29739:100;;462:1821:57;29865:7:123;29856:16;;;29852:100;;462:1821:57;29969:16:123;;29965:66;;462:1821:57;;;;;29978:7:123;462:1821:57;1545:94:117;462:1821:57;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;;1545:94:117;;;1652:247;462:1821:57;1706:111:117;;;;;;;;462:1821:57;1867:10:117;;1863:21;;462:1821:57;29978:7:123;1652:247:117;;;;1863:21;1879:5;;462:1821:57;;1917:357;462:1821;;1917:357;;462:1821;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;462:1821:57;;;2057:10;462:1821;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;1917:357;462:1821;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1917:357;;;;;;;;;;:::i;462:1821::-;;;;;;;;-1:-1:-1;462:1821:57;;;;;;;;-1:-1:-1;;462:1821:57;;;;;;;;1917:357;462:1821;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;462:1821:57;;-1:-1:-1;1917:357:57;462:1821;;;2057:10;462:1821;;;;;;-1:-1:-1;462:1821:57;;;;;;;;;-1:-1:-1;;462:1821:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;462:1821:57;;;;;;;;-1:-1:-1;;462:1821:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29965:66:123;462:1821:57;;;29965:66:123;;;29852:100;29865:7;29936:1;462:1821:57;;;;29852:100:123;;;29739;29752:7;462:1821:57;;;;;29739:100:123;;;29626;29639:7;29710:1;462:1821:57;;;;29626:100:123;;;29510:103;29523:8;29596:2;462:1821:57;;;;29510:103:123;;;29394;29407:8;462:1821:57;;;;;29394:103:123;;;29278;-1:-1:-1;462:1821:57;;-1:-1:-1;29291:8:123;462:1821:57;;29278:103:123;;462:1821:57;;;;;;;;;;;;;;1105:24;462:1821;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1105:24;462:1821;;;;;;;-1:-1:-1;462:1821:57;;;;;;;-1:-1:-1;462:1821:57;;-1:-1:-1;462:1821:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;-1:-1:-1;462:1821:57;;;;;-1:-1:-1;462:1821:57;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;462:1821:57;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;:::o","linkReferences":{}},"methodIdentifiers":{"bridgeReceiveTypeUrl()":"8f2edc84","constructMintCall(string,uint256)":"56d981a7","denom()":"c370b042","icaAddress()":"2ff02e27"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"bridgeReceiveTypeUrl_\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"denom_\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"icaAddress_\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"bridgeReceiveTypeUrl\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"receiver\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"constructMintCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"denom\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"icaAddress\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"This implementation encodes mint calls in protojson format for Cosmos SDK IFT module\",\"kind\":\"dev\",\"methods\":{\"constructMintCall(string,uint256)\":{\"details\":\"Encodes the mint call as protojson CosmosTx for Cosmos SDK ICS27-GMP module\",\"params\":{\"amount\":\"The amount of tokens to mint\",\"receiver\":\"The address of the receiver on the counterparty chain\"},\"returns\":{\"_0\":\"The constructed call data for the ICS27-GMP message\"}},\"constructor\":{\"params\":{\"bridgeReceiveTypeUrl_\":\"The type URL for MsgIFTMint\",\"denom_\":\"The denom of the token on the Cosmos SDK chain (e.g., \\\"uatom\\\", \\\"ibc/...\\\")\",\"icaAddress_\":\"The interchain account address on the Cosmos SDK chain\"}}},\"stateVariables\":{\"icaAddress\":{\"details\":\"Required to set the signer of the MsgIFTMint message (Cosmos SDK limitation)\"}},\"title\":\"Cosmos SDK IFT Send Call Constructor\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"bridgeReceiveTypeUrl()\":{\"notice\":\"The type URL for the MsgIFTMint message in the TokenFactory module\"},\"constructMintCall(string,uint256)\":{\"notice\":\"Constructs the ICS27-GMP call data for minting IFT tokens on the counterparty chain\"},\"constructor\":{\"notice\":\"Creates a new CosmosIFTSendCallConstructor\"},\"denom()\":{\"notice\":\"The denomination of the counterparty token on the Cosmos SDK chain\"},\"icaAddress()\":{\"notice\":\"The interchain account address of the submitter account on the Cosmos SDK chain\"}},\"notice\":\"Constructs ICS27-GMP call data for minting IFT tokens on Cosmos SDK-based counterparty chains\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/utils/CosmosIFTSendCallConstructor.sol\":\"CosmosIFTSendCallConstructor\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[\":@openzeppelin-contracts/=node_modules/@openzeppelin/contracts/\",\":@openzeppelin-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/=node_modules/@openzeppelin/\",\":@sp1-contracts/=node_modules/sp1-contracts/contracts/src/\",\":@uniswap/permit2/=node_modules/@uniswap/permit2/\",\":forge-std/=node_modules/forge-std/src/\",\":sp1-contracts/=node_modules/sp1-contracts/\"],\"viaIR\":true},\"sources\":{\"contracts/interfaces/IIFTSendCallConstructor.sol\":{\"keccak256\":\"0xaa49a7ac2dbdc445c5d6c2d49484f39c343da930f9d6dd62ad20b5b0c7a99e55\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://014c493ca7b15906323cc74464dbfacce33d5c1025670971074f5d54572c6970\",\"dweb:/ipfs/QmdbaM8S4jyT3PBDoHuWJnsrXx24K566qZgDjhD1EFzhrS\"]},\"contracts/utils/CosmosIFTSendCallConstructor.sol\":{\"keccak256\":\"0xc231e15347e5d16bca9d699025402b3ed0631ce4b9b389bb1e161d9a4f5a9646\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://73977e15c36a317001a3482bad415526461708d4f85028d0276f47eccaabb759\",\"dweb:/ipfs/QmeM1NatEEZ3a5bcL5uGZs7GxeniXo4sWX3jeXs6aGuQFH\"]},\"node_modules/@openzeppelin/contracts/utils/Panic.sol\":{\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a\",\"dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG\"]},\"node_modules/@openzeppelin/contracts/utils/Strings.sol\":{\"keccak256\":\"0xad148d59f05165f9217d0a9e1ac8f772abb02ea6aaad8a756315c532bf79f9f4\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://15e3599867c2182f5831e9268b274b2ef2047825837df6b4d81c9e89254b093e\",\"dweb:/ipfs/QmZbL7XAYr5RmaNaooPgZRmcDXaudfsYQfYD9y5iAECvpS\"]},\"node_modules/@openzeppelin/contracts/utils/math/Math.sol\":{\"keccak256\":\"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3\",\"dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB\"]},\"node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\":{\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8\",\"dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy\"]},\"node_modules/@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb1970fac7b64e6c09611e6691791e848d5e3fe410fa5899e7df2e0afd77a99e3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://db5fbb3dddd8b7047465b62575d96231ba8a2774d37fb4737fbf23340fabbb03\",\"dweb:/ipfs/QmVUSvooZKEdEdap619tcJjTLcAuH6QBdZqAzWwnAXZAWJ\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.28+commit.7893614a"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"string","name":"bridgeReceiveTypeUrl_","type":"string"},{"internalType":"string","name":"denom_","type":"string"},{"internalType":"string","name":"icaAddress_","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"stateMutability":"view","type":"function","name":"bridgeReceiveTypeUrl","outputs":[{"internalType":"string","name":"","type":"string"}]},{"inputs":[{"internalType":"string","name":"receiver","type":"string"},{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function","name":"constructMintCall","outputs":[{"internalType":"bytes","name":"","type":"bytes"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"denom","outputs":[{"internalType":"string","name":"","type":"string"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"icaAddress","outputs":[{"internalType":"string","name":"","type":"string"}]}],"devdoc":{"kind":"dev","methods":{"constructMintCall(string,uint256)":{"details":"Encodes the mint call as protojson CosmosTx for Cosmos SDK ICS27-GMP module","params":{"amount":"The amount of tokens to mint","receiver":"The address of the receiver on the counterparty chain"},"returns":{"_0":"The constructed call data for the ICS27-GMP message"}},"constructor":{"params":{"bridgeReceiveTypeUrl_":"The type URL for MsgIFTMint","denom_":"The denom of the token on the Cosmos SDK chain (e.g., \"uatom\", \"ibc/...\")","icaAddress_":"The interchain account address on the Cosmos SDK chain"}}},"version":1},"userdoc":{"kind":"user","methods":{"bridgeReceiveTypeUrl()":{"notice":"The type URL for the MsgIFTMint message in the TokenFactory module"},"constructMintCall(string,uint256)":{"notice":"Constructs the ICS27-GMP call data for minting IFT tokens on the counterparty chain"},"constructor":{"notice":"Creates a new CosmosIFTSendCallConstructor"},"denom()":{"notice":"The denomination of the counterparty token on the Cosmos SDK chain"},"icaAddress()":{"notice":"The interchain account address of the submitter account on the Cosmos SDK chain"}},"version":1}},"settings":{"remappings":["@openzeppelin-contracts/=node_modules/@openzeppelin/contracts/","@openzeppelin-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/","@openzeppelin/=node_modules/@openzeppelin/","@sp1-contracts/=node_modules/sp1-contracts/contracts/src/","@uniswap/permit2/=node_modules/@uniswap/permit2/","forge-std/=node_modules/forge-std/src/","sp1-contracts/=node_modules/sp1-contracts/"],"optimizer":{"enabled":true,"runs":10000},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"contracts/utils/CosmosIFTSendCallConstructor.sol":"CosmosIFTSendCallConstructor"},"evmVersion":"cancun","libraries":{},"viaIR":true},"sources":{"contracts/interfaces/IIFTSendCallConstructor.sol":{"keccak256":"0xaa49a7ac2dbdc445c5d6c2d49484f39c343da930f9d6dd62ad20b5b0c7a99e55","urls":["bzz-raw://014c493ca7b15906323cc74464dbfacce33d5c1025670971074f5d54572c6970","dweb:/ipfs/QmdbaM8S4jyT3PBDoHuWJnsrXx24K566qZgDjhD1EFzhrS"],"license":"MIT"},"contracts/utils/CosmosIFTSendCallConstructor.sol":{"keccak256":"0xc231e15347e5d16bca9d699025402b3ed0631ce4b9b389bb1e161d9a4f5a9646","urls":["bzz-raw://73977e15c36a317001a3482bad415526461708d4f85028d0276f47eccaabb759","dweb:/ipfs/QmeM1NatEEZ3a5bcL5uGZs7GxeniXo4sWX3jeXs6aGuQFH"],"license":"MIT"},"node_modules/@openzeppelin/contracts/utils/Panic.sol":{"keccak256":"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a","urls":["bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a","dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG"],"license":"MIT"},"node_modules/@openzeppelin/contracts/utils/Strings.sol":{"keccak256":"0xad148d59f05165f9217d0a9e1ac8f772abb02ea6aaad8a756315c532bf79f9f4","urls":["bzz-raw://15e3599867c2182f5831e9268b274b2ef2047825837df6b4d81c9e89254b093e","dweb:/ipfs/QmZbL7XAYr5RmaNaooPgZRmcDXaudfsYQfYD9y5iAECvpS"],"license":"MIT"},"node_modules/@openzeppelin/contracts/utils/math/Math.sol":{"keccak256":"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6","urls":["bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3","dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB"],"license":"MIT"},"node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol":{"keccak256":"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54","urls":["bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8","dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy"],"license":"MIT"},"node_modules/@openzeppelin/contracts/utils/math/SignedMath.sol":{"keccak256":"0xb1970fac7b64e6c09611e6691791e848d5e3fe410fa5899e7df2e0afd77a99e3","urls":["bzz-raw://db5fbb3dddd8b7047465b62575d96231ba8a2774d37fb4737fbf23340fabbb03","dweb:/ipfs/QmVUSvooZKEdEdap619tcJjTLcAuH6QBdZqAzWwnAXZAWJ"],"license":"MIT"}},"version":1},"id":57} \ No newline at end of file diff --git a/ibc-solidity/abi/bytecode/SP1ICS07Tendermint.json b/ibc-solidity/abi/bytecode/SP1ICS07Tendermint.json index d023e9a37..3c553641c 100644 --- a/ibc-solidity/abi/bytecode/SP1ICS07Tendermint.json +++ b/ibc-solidity/abi/bytecode/SP1ICS07Tendermint.json @@ -1 +1 @@ -{"abi":[{"type":"constructor","inputs":[{"name":"updateClientProgramVkey","type":"bytes32","internalType":"bytes32"},{"name":"membershipProgramVkey","type":"bytes32","internalType":"bytes32"},{"name":"updateClientAndMembershipProgramVkey","type":"bytes32","internalType":"bytes32"},{"name":"misbehaviourProgramVkey","type":"bytes32","internalType":"bytes32"},{"name":"sp1Verifier","type":"address","internalType":"address"},{"name":"_clientState","type":"bytes","internalType":"bytes"},{"name":"_consensusState","type":"bytes32","internalType":"bytes32"},{"name":"roleManager","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"ALLOWED_SP1_CLOCK_DRIFT","inputs":[],"outputs":[{"name":"","type":"uint16","internalType":"uint16"}],"stateMutability":"view"},{"type":"function","name":"DEFAULT_ADMIN_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"MEMBERSHIP_PROGRAM_VKEY","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"MISBEHAVIOUR_PROGRAM_VKEY","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"PROOF_SUBMITTER_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"UPDATE_CLIENT_AND_MEMBERSHIP_PROGRAM_VKEY","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"UPDATE_CLIENT_PROGRAM_VKEY","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"VERIFIER","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ISP1Verifier"}],"stateMutability":"view"},{"type":"function","name":"clientState","inputs":[],"outputs":[{"name":"chainId","type":"string","internalType":"string"},{"name":"trustLevel","type":"tuple","internalType":"struct IICS07TendermintMsgs.TrustThreshold","components":[{"name":"numerator","type":"uint8","internalType":"uint8"},{"name":"denominator","type":"uint8","internalType":"uint8"}]},{"name":"latestHeight","type":"tuple","internalType":"struct IICS02ClientMsgs.Height","components":[{"name":"revisionNumber","type":"uint64","internalType":"uint64"},{"name":"revisionHeight","type":"uint64","internalType":"uint64"}]},{"name":"trustingPeriod","type":"uint32","internalType":"uint32"},{"name":"unbondingPeriod","type":"uint32","internalType":"uint32"},{"name":"isFrozen","type":"bool","internalType":"bool"},{"name":"zkAlgorithm","type":"uint8","internalType":"enum IICS07TendermintMsgs.SupportedZkAlgorithm"}],"stateMutability":"view"},{"type":"function","name":"getClientState","inputs":[],"outputs":[{"name":"","type":"bytes","internalType":"bytes"}],"stateMutability":"view"},{"type":"function","name":"getConsensusStateHash","inputs":[{"name":"revisionHeight","type":"uint64","internalType":"uint64"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"getRoleAdmin","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"grantRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"hasRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"misbehaviour","inputs":[{"name":"misbehaviourMsg","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"multicall","inputs":[{"name":"data","type":"bytes[]","internalType":"bytes[]"}],"outputs":[{"name":"results","type":"bytes[]","internalType":"bytes[]"}],"stateMutability":"nonpayable"},{"type":"function","name":"renounceRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"callerConfirmation","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"revokeRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"updateClient","inputs":[{"name":"updateMsg","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"","type":"uint8","internalType":"enum ILightClientMsgs.UpdateResult"}],"stateMutability":"nonpayable"},{"type":"function","name":"verifyMembership","inputs":[{"name":"msg_","type":"tuple","internalType":"struct ILightClientMsgs.MsgVerifyMembership","components":[{"name":"proof","type":"bytes","internalType":"bytes"},{"name":"proofHeight","type":"tuple","internalType":"struct IICS02ClientMsgs.Height","components":[{"name":"revisionNumber","type":"uint64","internalType":"uint64"},{"name":"revisionHeight","type":"uint64","internalType":"uint64"}]},{"name":"path","type":"bytes[]","internalType":"bytes[]"},{"name":"value","type":"bytes","internalType":"bytes"}]}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"verifyNonMembership","inputs":[{"name":"msg_","type":"tuple","internalType":"struct ILightClientMsgs.MsgVerifyNonMembership","components":[{"name":"proof","type":"bytes","internalType":"bytes"},{"name":"proofHeight","type":"tuple","internalType":"struct IICS02ClientMsgs.Height","components":[{"name":"revisionNumber","type":"uint64","internalType":"uint64"},{"name":"revisionHeight","type":"uint64","internalType":"uint64"}]},{"name":"path","type":"bytes[]","internalType":"bytes[]"}]}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"event","name":"RoleAdminChanged","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"previousAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"newAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"error","name":"AccessControlBadConfirmation","inputs":[]},{"type":"error","name":"AccessControlUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"},{"name":"neededRole","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"AddressEmptyCode","inputs":[{"name":"target","type":"address","internalType":"address"}]},{"type":"error","name":"CannotHandleMisbehavior","inputs":[]},{"type":"error","name":"ChainIdMismatch","inputs":[{"name":"expected","type":"string","internalType":"string"},{"name":"actual","type":"string","internalType":"string"}]},{"type":"error","name":"ClientStateMismatch","inputs":[{"name":"expected","type":"bytes","internalType":"bytes"},{"name":"actual","type":"bytes","internalType":"bytes"}]},{"type":"error","name":"ConsensusStateHashMismatch","inputs":[{"name":"expected","type":"bytes32","internalType":"bytes32"},{"name":"actual","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"ConsensusStateNotFound","inputs":[]},{"type":"error","name":"ConsensusStateRootMismatch","inputs":[{"name":"expected","type":"bytes32","internalType":"bytes32"},{"name":"actual","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"EmptyValue","inputs":[]},{"type":"error","name":"FailedCall","inputs":[]},{"type":"error","name":"FeatureNotSupported","inputs":[]},{"type":"error","name":"FrozenClientState","inputs":[]},{"type":"error","name":"InvalidMembershipProof","inputs":[]},{"type":"error","name":"KeyValuePairNotInCache","inputs":[{"name":"path","type":"bytes[]","internalType":"bytes[]"},{"name":"value","type":"bytes","internalType":"bytes"}]},{"type":"error","name":"LengthIsOutOfRange","inputs":[{"name":"length","type":"uint256","internalType":"uint256"},{"name":"min","type":"uint256","internalType":"uint256"},{"name":"max","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"MembershipProofKeyNotFound","inputs":[{"name":"path","type":"bytes[]","internalType":"bytes[]"}]},{"type":"error","name":"MembershipProofValueMismatch","inputs":[{"name":"expected","type":"bytes","internalType":"bytes"},{"name":"actual","type":"bytes","internalType":"bytes"}]},{"type":"error","name":"ProofHeightMismatch","inputs":[{"name":"expectedRevisionNumber","type":"uint64","internalType":"uint64"},{"name":"expectedRevisionHeight","type":"uint64","internalType":"uint64"},{"name":"actualRevisionNumber","type":"uint64","internalType":"uint64"},{"name":"actualRevisionHeight","type":"uint64","internalType":"uint64"}]},{"type":"error","name":"ProofIsInTheFuture","inputs":[{"name":"now","type":"uint256","internalType":"uint256"},{"name":"proofTimestamp","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ProofIsTooOld","inputs":[{"name":"now","type":"uint256","internalType":"uint256"},{"name":"proofTimestamp","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"TrustThresholdMismatch","inputs":[{"name":"expectedNumerator","type":"uint256","internalType":"uint256"},{"name":"expectedDenominator","type":"uint256","internalType":"uint256"},{"name":"actualNumerator","type":"uint256","internalType":"uint256"},{"name":"actualDenominator","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"TrustingPeriodMismatch","inputs":[{"name":"expected","type":"uint256","internalType":"uint256"},{"name":"actual","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"TrustingPeriodTooLong","inputs":[{"name":"trustingPeriod","type":"uint256","internalType":"uint256"},{"name":"unbondingPeriod","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"UnbondingPeriodMismatch","inputs":[{"name":"expected","type":"uint256","internalType":"uint256"},{"name":"actual","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"UnknownMembershipProofType","inputs":[{"name":"proofType","type":"uint8","internalType":"uint8"}]},{"type":"error","name":"UnknownZkAlgorithm","inputs":[{"name":"algorithm","type":"uint8","internalType":"uint8"}]},{"type":"error","name":"VerificationKeyMismatch","inputs":[{"name":"expected","type":"bytes32","internalType":"bytes32"},{"name":"actual","type":"bytes32","internalType":"bytes32"}]}],"bytecode":{"object":"0x61012060405234610541576137268038038061001a81610564565b928339810161010082820312610541578151916020810151604082015160608301519061004960808501610589565b60a08501519095906001600160401b0381116105415785019080601f8301121561054157815161007b9260200161059d565b9261008d60e060c08701519601610589565b9660805260a05260c05260e05280518101906020820190602081840312610541576020810151906001600160401b038211610541570191829003601f1981019061012013610541576040519160e083016001600160401b0381118482101761052d5760405260208401516001600160401b038111610541576020908501019080601f830112156105415781516101259260200161059d565b825260408112610541576040610139610545565b916101458286016105dd565b8352610153606086016105dd565b602084015260208401928352603f19011261054157610170610545565b61017c608085016105eb565b815261018a60a085016105eb565b6020820152604083019081526101a260c085016105ff565b90606084019182526101b660e086016105ff565b92608085019384526101008601519586151587036105415760a0860196875261012001519460028610156105415760c08101958652518051906001600160401b03821161052d57600154600181811c91168015610523575b602082101461050f57601f81116104ac575b50602090601f831160011461043f5763ffffffff95949392915f9183610434575b50508160011b915f199060031b1c1916176001555b5160ff81511661ff00602060025493015160081b169161ffff191617176002555160018060401b0381511660035491602068010000000000000000600160801b0391015160401b169160018060801b031916171760035551169267ffffffff00000000600454925160201b169051151560401b92519160028310156104205769ff00000000000000000068ff00000000000000009360481b169469ff000000000000000000199160018060481b0319161716179116171760045560018060401b0360035460401c165f52600560205260405f205560018060a01b03166101005260045463ffffffff8116610708810163ffffffff811161040c5763ffffffff809360201c1692839116116103f757826001600160a01b0381166103de575061037c610706565b505b604051612efd908161078982396080518181816105570152611445015260a0518181816101f90152611e01015260c051818181610cb30152612185015260e0518181816102a00152610ac1015261010051818181610c780152611a1a0152f35b806103eb6103f192610610565b50610686565b5061037e565b6333fae18560e21b5f5260045260245260445ffd5b634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52602160045260245ffd5b015190505f80610241565b90601f1983169160015f52815f20925f5b818110610494575091600193918563ffffffff99989796941061047c575b505050811b01600155610256565b01515f1960f88460031b161c191690555f808061046e565b92936020600181928786015181550195019301610450565b60015f527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6601f840160051c81019160208510610505575b601f0160051c01905b8181106104fa5750610220565b5f81556001016104ed565b90915081906104e4565b634e487b7160e01b5f52602260045260245ffd5b90607f169061020e565b634e487b7160e01b5f52604160045260245ffd5b5f80fd5b60408051919082016001600160401b0381118382101761052d57604052565b6040519190601f01601f191682016001600160401b0381118382101761052d57604052565b51906001600160a01b038216820361054157565b9192916001600160401b03821161052d576105c1601f8301601f1916602001610564565b938285528282011161054157815f926020928387015e84010152565b519060ff8216820361054157565b51906001600160401b038216820361054157565b519063ffffffff8216820361054157565b6001600160a01b0381165f9081525f5160206137065f395f51905f52602052604090205460ff16610681576001600160a01b03165f8181525f5160206137065f395f51905f5260205260408120805460ff191660011790553391905f5160206136865f395f51905f528180a4600190565b505f90565b6001600160a01b0381165f9081525f5160206136a65f395f51905f52602052604090205460ff16610681576001600160a01b03165f8181525f5160206136a65f395f51905f5260205260408120805460ff191660011790553391905f5160206136e65f395f51905f52905f5160206136865f395f51905f529080a4600190565b5f80525f5160206136a65f395f51905f526020525f5160206136c65f395f51905f525460ff16610784575f8080525f5160206136a65f395f51905f526020525f5160206136c65f395f51905f52805460ff1916600117905533905f5160206136e65f395f51905f525f5160206136865f395f51905f528280a4600190565b5f9056fe6080806040526004361015610012575f80fd5b5f3560e01c90816301ffc9a714610cd6575080630225293e14610c9c57806308c84e7014610c4c5780630bece35614610b8957806323842fb814610b59578063248a9ca314610b2f5780632c3ee47414610b135780632f2ff15d14610ae4578063314d4dff14610aaa57806336568abe14610a4e5780634d6d9ffb1461096c5780635972185a14610932578063682ed5f01461080e57806391d14854146107c5578063a217fddf146107ab578063ac9650d81461066a578063bd3ce6b01461057a578063ca7242f914610540578063d547741f1461050a578063ddba65371461021c578063e45a6d0d146101e25763ef913a4b1461010e575f80fd5b346101de575f6003193601126101de576101da60405160208082015261012060408201526101c6816101436101608201610ec6565b60ff600254818116606085015260081c16608083015267ffffffffffffffff60035481811660a085015260401c1660c083015260ff60045463ffffffff811660e085015263ffffffff8160201c16610100850152818160401c16151561012085015260481c166101b28161105f565b61014083015203601f19810183528261103c565b604051918291602083526020830190610df8565b0390f35b5f80fd5b346101de575f6003193601126101de5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b346101de5761022a36610d74565b6004549160ff8360401c166104e2575f80527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e06020527f6e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac4754610298929060ff16156104d5575b8101906110d9565b6102c78151517f0000000000000000000000000000000000000000000000000000000000000000808214611189565b6020815101518051810160208101916020818303126101de57602081015167ffffffffffffffff81116101de57019061018090829003126101de576040519061030f82610fcc565b602081015167ffffffffffffffff81116101de57839082016020019061033491611260565b825261034260408201611348565b60208301908152906103578460608301611219565b604084019081529161036c8560a08401611219565b60608501908152946103818160e08501611365565b9260808601938452610140019061039791611365565b9360a081019485525190516fffffffffffffffffffffffffffffffff166103bd916126e8565b516040805182516fffffffffffffffffffffffffffffffff16602080830191825284015182840152919092015160608084019190915282529061040160808261103c565b51902090516020015167ffffffffffffffff1661041d90611649565b61042a919081811461187c565b516040805182516fffffffffffffffffffffffffffffffff16602080830191825284015182840152919092015160608084019190915282529061046e60808261103c565b51902090516020015167ffffffffffffffff1661048a90611649565b610497919081811461187c565b516104a190611a03565b7fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff1668010000000000000000176004555f80f35b6104dd61178e565b610290565b7f928b1233000000000000000000000000000000000000000000000000000000005f5260045ffd5b346101de5761053e61051b36610dc5565b90610539610534825f525f602052600160405f20015490565b611816565b611ba5565b005b346101de575f6003193601126101de5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b346101de575f6003193601126101de576040516105a18161059a81610ec6565b038261103c565b6101206040516105b081610f83565b60025460ff8116825260ff602083019160081c16815260ff6040516105d481610f83565b67ffffffffffffffff600354818116835281602084019160401c168152816004549385808660481c1697816106146040519d8d8f9e8f9081520190610df8565b9a511660208c0152511660408a0152511660608801525116608086015263ffffffff811660a086015263ffffffff8160201c1660c086015260401c16151560e08401526106608161105f565b6101008301520390f35b346101de5760206003193601126101de5760043567ffffffffffffffff81116101de57366023820112156101de57806004013567ffffffffffffffff81116101de57602482013660248360051b850101116101de5760405160206106ce818361103c565b5f825280820192601f1982013685376106e685611735565b956106f4604051978861103c565b858752601f1961070387611735565b01835f5b82811061079b575050505f5b868110156107885760019061076c61076661073660248460051b87010187611690565b9190888b846040519586948486013783018281015f81528d519283915e01015f815203601f19810183528261103c565b30612621565b610776828b61174d565b52610781818a61174d565b5001610713565b604051848152806101da8187018b610e1d565b606082828c010152018490610707565b346101de575f6003193601126101de5760206040515f8152f35b346101de576107d336610dc5565b905f525f60205273ffffffffffffffffffffffffffffffffffffffff60405f2091165f52602052602060ff60405f2054166040519015158152f35b346101de5760206003193601126101de5760043567ffffffffffffffff81116101de578060040160a060031983360301126101de5760ff60045460401c166104e2575f80527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e06020527f6e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac475460ff1615610925575b60848201916108b18383611690565b9050156108fd57602092826108c9816108f595611690565b60246108ed6108e66108de60648901876116e1565b979096611690565b3691611085565b950191611cee565b604051908152f35b7f1208b21b000000000000000000000000000000000000000000000000000000005f5260045ffd5b61092d61178e565b6108a2565b346101de575f6003193601126101de5760206040517fbd893629a699470e4ec82a5715bb4981fdaacc5d0a728bf5f55b801d8f4ef10b8152f35b346101de5760206003193601126101de5760043567ffffffffffffffff81116101de5780600401608060031983360301126101de5760ff60045460401c166104e2575f80527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e060209081527f6e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac475490926108f592909160ff1615610a41575b610a24610a178280611690565b91909260648501906116e1565b929091602460405195610a37898861103c565b5f87520191611cee565b610a4961178e565b610a0a565b346101de57610a5c36610dc5565b3373ffffffffffffffffffffffffffffffffffffffff821603610a825761053e91611ba5565b7f6697b232000000000000000000000000000000000000000000000000000000005f5260045ffd5b346101de575f6003193601126101de5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b346101de5761053e610af536610dc5565b90610b0e610534825f525f602052600160405f20015490565b611ad3565b346101de575f6003193601126101de5760206040516107088152f35b346101de5760206003193601126101de5760206108f56004355f525f602052600160405f20015490565b346101de5760206003193601126101de5760043567ffffffffffffffff811681036101de576108f5602091611649565b346101de57610b9736610d74565b60ff60045460401c166104e2575f80527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e06020527f6e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac4754610bff929060ff1615610c3f57611431565b6040516003821015610c12576020918152f35b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b610c4761178e565b611431565b346101de575f6003193601126101de57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346101de575f6003193601126101de5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b346101de5760206003193601126101de57600435907fffffffff0000000000000000000000000000000000000000000000000000000082168092036101de57817f7965db0b0000000000000000000000000000000000000000000000000000000060209314908115610d4a575b5015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501483610d43565b9060206003198301126101de5760043567ffffffffffffffff81116101de57826023820112156101de5780600401359267ffffffffffffffff84116101de57602484830101116101de576024019190565b60031960409101126101de576004359060243573ffffffffffffffffffffffffffffffffffffffff811681036101de5790565b90601f19601f602080948051918291828752018686015e5f8582860101520116010190565b9080602083519182815201916020808360051b8301019401925f915b838310610e4857505050505090565b9091929394602080610e6683601f1986600196030187528951610df8565b97019301930191939290610e39565b90600182811c92168015610ebc575b6020831014610e8f57565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b91607f1691610e84565b6001545f9291610ed582610e75565b8082529160018116908115610f495750600114610ef0575050565b60015f9081529293509091907fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65b838310610f2f575060209250010190565b600181602092949394548385870101520191019190610f1e565b60209495507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091509291921683830152151560051b010190565b6040810190811067ffffffffffffffff821117610f9f57604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b60c0810190811067ffffffffffffffff821117610f9f57604052565b6020810190811067ffffffffffffffff821117610f9f57604052565b6060810190811067ffffffffffffffff821117610f9f57604052565b60e0810190811067ffffffffffffffff821117610f9f57604052565b90601f601f19910116810190811067ffffffffffffffff821117610f9f57604052565b60021115610c1257565b67ffffffffffffffff8111610f9f57601f01601f191660200190565b92919261109182611069565b9161109f604051938461103c565b8294818452818301116101de578281602093845f960137010152565b9080601f830112156101de578160206110d693359101611085565b90565b6020818303126101de5780359067ffffffffffffffff82116101de5701906020828203126101de576040519161110e83610fe8565b80359067ffffffffffffffff82116101de57016060818303126101de576040519161113883611004565b81358352602082013567ffffffffffffffff81116101de578161115c9184016110bb565b6020840152604082013567ffffffffffffffff81116101de5761117f92016110bb565b6040820152815290565b15611192575050565b7fd56bdc26000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b9291926111cc82611069565b916111da604051938461103c565b8294818452818301116101de578281602093845f96015e010152565b519060ff821682036101de57565b519067ffffffffffffffff821682036101de57565b91908260409103126101de5760405161123181610f83565b602061124a81839561124281611204565b855201611204565b910152565b519063ffffffff821682036101de57565b91908281039261012084126101de576040519161127c83611020565b8294825167ffffffffffffffff81116101de57830182601f820112156101de576040916112b284836020601f19955191016111c0565b865201126101de576112f7906040516112ca81610f83565b6112d6602085016111f6565b81526112e4604085016111f6565b6020820152602085015260608301611219565b604083015261130860a0820161124f565b606083015261131960c0820161124f565b608083015260e08101519081151582036101de576101009160a084015201519060028210156101de5760c00152565b51906fffffffffffffffffffffffffffffffff821682036101de57565b91908260609103126101de5760405161137d81611004565b604080829461138b81611348565b8452602081015160208501520151910152565b9190610180838203126101de57604051906113b882610fcc565b819380519167ffffffffffffffff83116101de57610140826113e18360a09661124a9601611260565b86526113f08360208301611365565b60208701526114028360808301611365565b604087015261141360e08201611348565b6060870152611426836101008301611219565b608087015201611219565b61143d918101906110d9565b61146c8151517f0000000000000000000000000000000000000000000000000000000000000000808214611189565b60208151015180518101906020818303126101de5760208101519167ffffffffffffffff83116101de576114a792602080920192010161139e565b906114b1826118b3565b6114ba82611946565b916003831015610c1257826115ec57908167ffffffffffffffff6020604060a06110d6960193845184848201511685600354851c168111611564575b505001516040516115498161153b858201948591909160408060608301946fffffffffffffffffffffffffffffffff8151168452602081015160208501520151910152565b03601f19810183528261103c565b51902092510151165f52600560205260405f20555b51611a03565b6115a3866115e593511667ffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006003541617600355565b7fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff6fffffffffffffffff00000000000000006003549260401b16911617600355565b5f806114f6565b5060018203611631576110d690680100000000000000007fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff600454161760045561155e565b60028214611642576110d69061155e565b5050600290565b67ffffffffffffffff165f52600560205260405f205480156116685790565b7f5b48b457000000000000000000000000000000000000000000000000000000005f5260045ffd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156101de570180359067ffffffffffffffff82116101de576020019181360383136101de57565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156101de570180359067ffffffffffffffff82116101de57602001918160051b360383136101de57565b67ffffffffffffffff8111610f9f5760051b60200190565b80518210156117615760209160051b010190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b335f9081527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e0602052604090205460ff16156117c657565b7fe2517d3f000000000000000000000000000000000000000000000000000000005f52336004527fbd893629a699470e4ec82a5715bb4981fdaacc5d0a728bf5f55b801d8f4ef10b60245260445ffd5b805f525f60205260405f2073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f2054161561184d5750565b7fe2517d3f000000000000000000000000000000000000000000000000000000005f523360045260245260445ffd5b15611885575050565b7f6d23e8a3000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b611944906118d981516fffffffffffffffffffffffffffffffff606084015116906126e8565b61193c67ffffffffffffffff602060808185015160405161192e8161153b868201948591909160408060608301946fffffffffffffffffffffffffffffffff8151168452602081015160208501520151910152565b519020940151015116611649565b80821461187c565b565b67ffffffffffffffff602060a08301510151165f52600560205260405f205480155f146119735750505f90565b604082019081516040516119bc8161153b60208201948591909160408060608301946fffffffffffffffffffffffffffffffff8151168452602081015160208501520151910152565b51902014918215926119da575b5050156119d557600190565b600290565b6fffffffffffffffffffffffffffffffff91925060208291015151169151511611155f806119c9565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169080516040602083015192015192803b156101de575f92611a9b92611aad604051968795869485947f41493c600000000000000000000000000000000000000000000000000000000086526004860152606060248601526064850190610df8565b90600319848303016044850152610df8565b03915afa8015611ac857611abe5750565b5f6119449161103c565b6040513d5f823e3d90fd5b805f525f60205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260ff60405f205416155f14611b9f57805f525f60205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260405f2060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905573ffffffffffffffffffffffffffffffffffffffff339216907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d5f80a4600190565b50505f90565b805f525f60205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260ff60405f2054165f14611b9f57805f525f60205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260405f207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00815416905573ffffffffffffffffffffffffffffffffffffffff339216907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b5f80a4600190565b3567ffffffffffffffff811681036101de5790565b929190611c8e81611735565b93611c9c604051958661103c565b602085838152019160051b8101918383116101de5781905b838210611cc2575050505050565b813567ffffffffffffffff81116101de57602091611ce387849387016110bb565b815201910190611cb4565b9094929193948015612568578101906020818303126101de5780359067ffffffffffffffff82116101de57016040818303126101de5760405191611d3183610f83565b813560028110156101de578352602082013567ffffffffffffffff81116101de57611d5c92016110bb565b90602081019182528051611d6f8161105f565b611d788161105f565b611fe5575051908151820160208101926020818303126101de57602081015167ffffffffffffffff81116101de570190608090829003126101de5760405192611dc084610f83565b602082015167ffffffffffffffff81116101de5782611de9836020604094611df1970101612a5a565b865201611365565b9460208301958652611e288351517f0000000000000000000000000000000000000000000000000000000000000000808214611189565b6020835101519182518301926020818503126101de5760208101519067ffffffffffffffff82116101de5701926040848203126101de5760405193611e6c85610f83565b6020810151855260408101519167ffffffffffffffff83116101de57611e99926020809201920101612ac0565b94611eb360208501968088525180151580611fd957612c0d565b5f805b87518051831015611fa657611ece83611ee19261174d565b5151611edb368888611c82565b90612da9565b15611f9c57508694611f40611f55956fffffffffffffffffffffffffffffffff9a9895611f3961155e966020633b9aca009f9d8198611f20915161174d565b51015190815181518082149182611f88575b5050612c4b565b6001612c99565b51950194611f4d86611c6d565b875191612e1b565b516001815111611f69575b50505151160490565b611f75611f8192611c6d565b90848451511691612eab565b5f80611f60565b909150898401209089830120145f80611f32565b9060010190611eb6565b5061155e92506020915094611f40611f55956fffffffffffffffffffffffffffffffff9a9895633b9aca009c9a98612c99565b5061ffff811115612c0d565b94906001869593949551611ff88161105f565b6120018161105f565b146120485760ff86516120138161105f565b61201c8161105f565b7fd3a2e6c9000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b90919293945051926060602060405161206081610f83565b60405161206c81610fcc565b60405161207881611020565b84815260405161208781610f83565b5f81525f858201528482015260405161209f81610f83565b5f81525f8582015260408201525f858201525f60808201525f60a08201525f60c082015281526120cd612a22565b838201526120d9612a22565b60408201525f848201526040516120ef81610f83565b5f81525f84820152608082015260405161210881610f83565b5f81525f8482015260a08201528152015283518401936020818603126101de5760208101519067ffffffffffffffff82116101de5701936020858203126101de576040519461215686610fe8565b60208101519067ffffffffffffffff82116101de57602061217f92816121ac9501920101612a5a565b808652517f0000000000000000000000000000000000000000000000000000000000000000808214611189565b602084510151948551860160208101966020818303126101de57602081015167ffffffffffffffff81116101de570190604090829003126101de57604051966121f488610f83565b602082015167ffffffffffffffff81116101de578160206122179285010161139e565b885260408201519167ffffffffffffffff83116101de5761223b9201602001612ac0565b9361225560208801958087525180151580611fd957612c0d565b602081019561226387611c6d565b67ffffffffffffffff60a08a5101519181602084015116918291161480612549575b61228e85611c6d565b9267ffffffffffffffff6122a18c611c6d565b91511691156124fb57505050506122bc9061155e89516118b3565b6122c68751611946565b6003811015610c1257806124ca57506122de86611c6d565b67ffffffffffffffff8060035460401c16911611612477575b506040865101516040516123408161153b60208201948591909160408060608301946fffffffffffffffffffffffffffffffff8151168452602081015160208501520151910152565b51902067ffffffffffffffff61235587611c6d565b165f52600560205260405f20555b5f805b8551805183101561244c57611ece8361237e9261174d565b156124425750633b9aca0096936fffffffffffffffffffffffffffffffff9693611f39879460206123b56123cd9660409b5161174d565b5101519081518151808214918261242c575050612c4b565b6123f48351858101519067ffffffffffffffff602060a08185015193015101511690612e1b565b51600181511161240a575b505051015151160490565b61241661242592611c6d565b90858585510151511691612eab565b5f806123ff565b9091506020840120906020830120145f80611f32565b9060010190612366565b5060409592506123cd9150936fffffffffffffffffffffffffffffffff9693633b9aca009895612c99565b6124836124b891611c6d565b67ffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006003541617600355565b6124c46115a386611c6d565b5f6122f7565b6001915003612363577f59bc8fd3000000000000000000000000000000000000000000000000000000005f5260045ffd5b6084945067ffffffffffffffff9081604051957fb8d8167e00000000000000000000000000000000000000000000000000000000875216600486015216602484015260448301526064820152fd5b5061255384611c6d565b67ffffffffffffffff80845116911614612285565b5050909161257b60206125909201611c6d565b916040519461258986610f83565b3691611c82565b8352602083019182526040516125af8161153b86602083019586612954565b5190205c9151905182156125c9575050633b9aca00900490565b9061261d61260b926040519384937ff06fc33b000000000000000000000000000000000000000000000000000000008552604060048601526044850190610e1d565b90600319848303016024850152610df8565b0390fd5b905f8091602081519101845af480806126d5575b156126555750506040513d81523d5f602083013e60203d82010160405290565b1561269c5773ffffffffffffffffffffffffffffffffffffffff907f9996b315000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b3d156126ad576040513d5f823e3d90fd5b7fd6bda275000000000000000000000000000000000000000000000000000000005f5260045ffd5b503d1515806126355750813b1515612635565b906fffffffffffffffffffffffffffffffff633b9aca00911604428111612925578042034281116128f857610708106128c9575080515161272a600154610e75565b14806128a2575b815190156128625750602081015160ff815116906002549160ff8316928382149283612849575b6020015160ff169215612801575050505063ffffffff606082015116906004549163ffffffff83168082036127d357505063ffffffff608081920151169160201c168082036127a5575050565b7f1eb5c1eb000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b7f73b1bde3000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b6084945060ff90604051947fd382033a000000000000000000000000000000000000000000000000000000008652600486015260081c16602484015260448301526064820152fd5b6020810151600883901c60ff9081169116149350612758565b61261d906040519182917ff6b6676b0000000000000000000000000000000000000000000000000000000083526040600484015261260b60448401610ec6565b508051602081519101206040516128bc8161059a81610ec6565b6020815191012014612731565b7f12e74add000000000000000000000000000000000000000000000000000000005f524260045260245260445ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b7f20daedb6000000000000000000000000000000000000000000000000000000005f524260045260245260445ffd5b9067ffffffffffffffff90939293168152604060208201526080810190835191604080830152825180915260a0820190602060a08260051b8501019401915f905b8282106129d9575050505060206110d6939401519060607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc082850301910152610df8565b90919294602080612a14837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6089600196030186528951610df8565b970192019201909291612995565b60405190612a2f82611004565b5f6040838281528260208201520152565b9080601f830112156101de5781516110d6926020016111c0565b91906060838203126101de5760405190612a7382611004565b819380518352602081015167ffffffffffffffff81116101de5782612a99918301612a40565b602084015260408101519167ffffffffffffffff83116101de5760409261124a9201612a40565b9080601f830112156101de57815191612ad883611735565b92612ae6604051948561103c565b80845260208085019160051b830101918383116101de5760208101915b838310612b1257505050505090565b825167ffffffffffffffff81116101de578201906040601f1983880301126101de5760405190612b4182610f83565b602083015167ffffffffffffffff81116101de5760209084010187601f820112156101de578051612b7181611735565b91612b7f604051938461103c565b81835260208084019260051b820101918a83116101de5760208201905b838210612bdf5750505050825260408301519167ffffffffffffffff83116101de57612bd088602080969581960101612a40565b83820152815201920191612b03565b815167ffffffffffffffff81116101de57602091612c028e848094880101612a40565b815201910190612b9c565b15612c155750565b7fb0369c31000000000000000000000000000000000000000000000000000000005f52600452600160245261ffff60445260645ffd5b91909115612c57575050565b9061261d61260b926040519384937f5f1ca381000000000000000000000000000000000000000000000000000000008552604060048601526044850190610df8565b91909115612ca5575050565b604051907ffef760c700000000000000000000000000000000000000000000000000000000825280602483016020600485015252604482019260448260051b84010191815f907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603015b838310612d1e5786860387fd5b90919293947fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc8782030188528535828112156101de578301906020823592019167ffffffffffffffff81116101de5780360383136101de57602082601f19601f8480600198869897879852868601375f85828601015201160101970198019301919096939296612d11565b908151815103611b9f575f5b8251811015612e1357612dc8818461174d565b5151612dd4828461174d565b515103612e0c57612de5818461174d565b5160208151910120612df7828461174d565b516020815191012003612e0c57600101612db5565b5050505f90565b505050600190565b91612e7060209261193c60405185810190612e678161153b888591909160408060608301946fffffffffffffffffffffffffffffffff8151168452602081015160208501520151910152565b51902091611649565b0151808203612e7d575050565b7f4b2dfe98000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b929190925f5b8451811015612ee9578083612ec86001938861174d565b51604051612edf8161153b60208201948986612954565b5190205d01612eb1565b505050905056fea164736f6c634300081c000a2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e06e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac47bd893629a699470e4ec82a5715bb4981fdaacc5d0a728bf5f55b801d8f4ef10bad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5","sourceMap":"1355:25496:38:-:0;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;;;;;1355:25496:38;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;3774:52;1355:25496;3774:52;1355:25496;3836:47;1355:25496;3893:80;1355:25496;3983:51;1355:25496;;4059:60;;;1355:25496;4059:60;;1355:25496;;;;;;;;;4059:60;;1355:25496;;-1:-1:-1;;;;;1355:25496:38;;;;;;;;;-1:-1:-1;;1355:25496:38;;;;-1:-1:-1;1355:25496:38;;;;;;;;-1:-1:-1;;;;;1355:25496:38;;;;;;;;;;;;;;-1:-1:-1;;;;;1355:25496:38;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1355:25496:38;;;;;;;;;;;;;;;;-1:-1:-1;1355:25496:38;;;;;;;;;;;-1:-1:-1;1355:25496:38;;;;;;;;;;;;;;;;-1:-1:-1;;1355:25496:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1355:25496:38;4129:21;1355:25496;;;-1:-1:-1;1355:25496:38;;;;;;;;;4220:36;1355:25496;;;;;2472:10;;;1355:25496;2472:10;;;;1355:25496;2472:10;;1355:25496;2472:10;1355:25496;;;;;4288:83;2472:10;;1355:25496;-1:-1:-1;;;;;1355:25496:38;;;;4529:44;;;:::i;:::-;;4484:351;1355:25496;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4484:351;4637:43;;4736:45;4637:43;;:::i;:::-;;4736:45;:::i;:::-;;4484:351;;2472:10;;;;-1:-1:-1;2472:10:38;1355:25496;2472:10;;;;-1:-1:-1;2472:10:38;;1355:25496;;;-1:-1:-1;2472:10:38;;1355:25496;2472:10;;-1:-1:-1;2472:10:38;1355:25496;;;;-1:-1:-1;1355:25496:38;;;;;-1:-1:-1;1355:25496:38;;;;;-1:-1:-1;1355:25496:38;;;;;;;;;;;;-1:-1:-1;1355:25496:38;;-1:-1:-1;1355:25496:38;;-1:-1:-1;1355:25496:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1355:25496:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1355:25496:38;;;;;;;;;-1:-1:-1;1355:25496:38;;;;;;;;-1:-1:-1;1355:25496:38;;;;;-1:-1:-1;1355:25496:38;;;;;;;;;;;;-1:-1:-1;1355:25496:38;;;;;-1:-1:-1;1355:25496:38;;-1:-1:-1;1355:25496:38;;;;;;;;;;-1:-1:-1;;;;;1355:25496:38;;;;;;;;;;:::o;:::-;;;;;;;-1:-1:-1;;1355:25496:38;;;-1:-1:-1;;;;;1355:25496:38;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;;;1355:25496:38;;;;;;:::o;:::-;;;;-1:-1:-1;;;;;1355:25496:38;;;;;;;;-1:-1:-1;;1355:25496:38;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;;;1355:25496:38;;;;;;:::o;:::-;;;;;;;;;;:::o;6155:316:84:-;-1:-1:-1;;;;;1355:25496:38;;;;;;-1:-1:-1;;;;;;;;;;;1355:25496:38;;;;;;;;;;-1:-1:-1;;;;;1355:25496:38;;;;;-1:-1:-1;;;;;;;;;;;1355:25496:38;;;;;;;-1:-1:-1;;1355:25496:38;;;;;735:10:112;;1355:25496:38;-1:-1:-1;;;;;;;;;;;1355:25496:38;;6346:40:84;6323:4;6400:11;:::o;6248:217::-;6442:12;1355:25496:38;6442:12:84;:::o;6155:316::-;-1:-1:-1;;;;;1355:25496:38;;;;;;-1:-1:-1;;;;;;;;;;;1355:25496:38;;;;;;;;;;-1:-1:-1;;;;;1355:25496:38;;;;;-1:-1:-1;;;;;;;;;;;1355:25496:38;;;;;;;-1:-1:-1;;1355:25496:38;;;;;735:10:112;;1355:25496:38;-1:-1:-1;;;;;;;;;;;2576:33:38;-1:-1:-1;;;;;;;;;;;6346:40:84;1355:25496:38;6346:40:84;6323:4;6400:11;:::o;6155:316::-;1355:25496:38;;;-1:-1:-1;;;;;;;;;;;1355:25496:38;;-1:-1:-1;;;;;;;;;;;1355:25496:38;;;;;;;;;-1:-1:-1;;;;;;;;;;;1355:25496:38;;-1:-1:-1;;;;;;;;;;;1355:25496:38;;-1:-1:-1;;1355:25496:38;6323:4:84;1355:25496:38;;;735:10:112;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;1355:25496:38;;6346:40:84;6323:4;6400:11;:::o;6248:217::-;1355:25496:38;6442:12:84;:::o","linkReferences":{}},"deployedBytecode":{"object":"0x6080806040526004361015610012575f80fd5b5f3560e01c90816301ffc9a714610cd6575080630225293e14610c9c57806308c84e7014610c4c5780630bece35614610b8957806323842fb814610b59578063248a9ca314610b2f5780632c3ee47414610b135780632f2ff15d14610ae4578063314d4dff14610aaa57806336568abe14610a4e5780634d6d9ffb1461096c5780635972185a14610932578063682ed5f01461080e57806391d14854146107c5578063a217fddf146107ab578063ac9650d81461066a578063bd3ce6b01461057a578063ca7242f914610540578063d547741f1461050a578063ddba65371461021c578063e45a6d0d146101e25763ef913a4b1461010e575f80fd5b346101de575f6003193601126101de576101da60405160208082015261012060408201526101c6816101436101608201610ec6565b60ff600254818116606085015260081c16608083015267ffffffffffffffff60035481811660a085015260401c1660c083015260ff60045463ffffffff811660e085015263ffffffff8160201c16610100850152818160401c16151561012085015260481c166101b28161105f565b61014083015203601f19810183528261103c565b604051918291602083526020830190610df8565b0390f35b5f80fd5b346101de575f6003193601126101de5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b346101de5761022a36610d74565b6004549160ff8360401c166104e2575f80527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e06020527f6e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac4754610298929060ff16156104d5575b8101906110d9565b6102c78151517f0000000000000000000000000000000000000000000000000000000000000000808214611189565b6020815101518051810160208101916020818303126101de57602081015167ffffffffffffffff81116101de57019061018090829003126101de576040519061030f82610fcc565b602081015167ffffffffffffffff81116101de57839082016020019061033491611260565b825261034260408201611348565b60208301908152906103578460608301611219565b604084019081529161036c8560a08401611219565b60608501908152946103818160e08501611365565b9260808601938452610140019061039791611365565b9360a081019485525190516fffffffffffffffffffffffffffffffff166103bd916126e8565b516040805182516fffffffffffffffffffffffffffffffff16602080830191825284015182840152919092015160608084019190915282529061040160808261103c565b51902090516020015167ffffffffffffffff1661041d90611649565b61042a919081811461187c565b516040805182516fffffffffffffffffffffffffffffffff16602080830191825284015182840152919092015160608084019190915282529061046e60808261103c565b51902090516020015167ffffffffffffffff1661048a90611649565b610497919081811461187c565b516104a190611a03565b7fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff1668010000000000000000176004555f80f35b6104dd61178e565b610290565b7f928b1233000000000000000000000000000000000000000000000000000000005f5260045ffd5b346101de5761053e61051b36610dc5565b90610539610534825f525f602052600160405f20015490565b611816565b611ba5565b005b346101de575f6003193601126101de5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b346101de575f6003193601126101de576040516105a18161059a81610ec6565b038261103c565b6101206040516105b081610f83565b60025460ff8116825260ff602083019160081c16815260ff6040516105d481610f83565b67ffffffffffffffff600354818116835281602084019160401c168152816004549385808660481c1697816106146040519d8d8f9e8f9081520190610df8565b9a511660208c0152511660408a0152511660608801525116608086015263ffffffff811660a086015263ffffffff8160201c1660c086015260401c16151560e08401526106608161105f565b6101008301520390f35b346101de5760206003193601126101de5760043567ffffffffffffffff81116101de57366023820112156101de57806004013567ffffffffffffffff81116101de57602482013660248360051b850101116101de5760405160206106ce818361103c565b5f825280820192601f1982013685376106e685611735565b956106f4604051978861103c565b858752601f1961070387611735565b01835f5b82811061079b575050505f5b868110156107885760019061076c61076661073660248460051b87010187611690565b9190888b846040519586948486013783018281015f81528d519283915e01015f815203601f19810183528261103c565b30612621565b610776828b61174d565b52610781818a61174d565b5001610713565b604051848152806101da8187018b610e1d565b606082828c010152018490610707565b346101de575f6003193601126101de5760206040515f8152f35b346101de576107d336610dc5565b905f525f60205273ffffffffffffffffffffffffffffffffffffffff60405f2091165f52602052602060ff60405f2054166040519015158152f35b346101de5760206003193601126101de5760043567ffffffffffffffff81116101de578060040160a060031983360301126101de5760ff60045460401c166104e2575f80527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e06020527f6e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac475460ff1615610925575b60848201916108b18383611690565b9050156108fd57602092826108c9816108f595611690565b60246108ed6108e66108de60648901876116e1565b979096611690565b3691611085565b950191611cee565b604051908152f35b7f1208b21b000000000000000000000000000000000000000000000000000000005f5260045ffd5b61092d61178e565b6108a2565b346101de575f6003193601126101de5760206040517fbd893629a699470e4ec82a5715bb4981fdaacc5d0a728bf5f55b801d8f4ef10b8152f35b346101de5760206003193601126101de5760043567ffffffffffffffff81116101de5780600401608060031983360301126101de5760ff60045460401c166104e2575f80527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e060209081527f6e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac475490926108f592909160ff1615610a41575b610a24610a178280611690565b91909260648501906116e1565b929091602460405195610a37898861103c565b5f87520191611cee565b610a4961178e565b610a0a565b346101de57610a5c36610dc5565b3373ffffffffffffffffffffffffffffffffffffffff821603610a825761053e91611ba5565b7f6697b232000000000000000000000000000000000000000000000000000000005f5260045ffd5b346101de575f6003193601126101de5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b346101de5761053e610af536610dc5565b90610b0e610534825f525f602052600160405f20015490565b611ad3565b346101de575f6003193601126101de5760206040516107088152f35b346101de5760206003193601126101de5760206108f56004355f525f602052600160405f20015490565b346101de5760206003193601126101de5760043567ffffffffffffffff811681036101de576108f5602091611649565b346101de57610b9736610d74565b60ff60045460401c166104e2575f80527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e06020527f6e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac4754610bff929060ff1615610c3f57611431565b6040516003821015610c12576020918152f35b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b610c4761178e565b611431565b346101de575f6003193601126101de57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346101de575f6003193601126101de5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b346101de5760206003193601126101de57600435907fffffffff0000000000000000000000000000000000000000000000000000000082168092036101de57817f7965db0b0000000000000000000000000000000000000000000000000000000060209314908115610d4a575b5015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501483610d43565b9060206003198301126101de5760043567ffffffffffffffff81116101de57826023820112156101de5780600401359267ffffffffffffffff84116101de57602484830101116101de576024019190565b60031960409101126101de576004359060243573ffffffffffffffffffffffffffffffffffffffff811681036101de5790565b90601f19601f602080948051918291828752018686015e5f8582860101520116010190565b9080602083519182815201916020808360051b8301019401925f915b838310610e4857505050505090565b9091929394602080610e6683601f1986600196030187528951610df8565b97019301930191939290610e39565b90600182811c92168015610ebc575b6020831014610e8f57565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b91607f1691610e84565b6001545f9291610ed582610e75565b8082529160018116908115610f495750600114610ef0575050565b60015f9081529293509091907fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65b838310610f2f575060209250010190565b600181602092949394548385870101520191019190610f1e565b60209495507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091509291921683830152151560051b010190565b6040810190811067ffffffffffffffff821117610f9f57604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b60c0810190811067ffffffffffffffff821117610f9f57604052565b6020810190811067ffffffffffffffff821117610f9f57604052565b6060810190811067ffffffffffffffff821117610f9f57604052565b60e0810190811067ffffffffffffffff821117610f9f57604052565b90601f601f19910116810190811067ffffffffffffffff821117610f9f57604052565b60021115610c1257565b67ffffffffffffffff8111610f9f57601f01601f191660200190565b92919261109182611069565b9161109f604051938461103c565b8294818452818301116101de578281602093845f960137010152565b9080601f830112156101de578160206110d693359101611085565b90565b6020818303126101de5780359067ffffffffffffffff82116101de5701906020828203126101de576040519161110e83610fe8565b80359067ffffffffffffffff82116101de57016060818303126101de576040519161113883611004565b81358352602082013567ffffffffffffffff81116101de578161115c9184016110bb565b6020840152604082013567ffffffffffffffff81116101de5761117f92016110bb565b6040820152815290565b15611192575050565b7fd56bdc26000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b9291926111cc82611069565b916111da604051938461103c565b8294818452818301116101de578281602093845f96015e010152565b519060ff821682036101de57565b519067ffffffffffffffff821682036101de57565b91908260409103126101de5760405161123181610f83565b602061124a81839561124281611204565b855201611204565b910152565b519063ffffffff821682036101de57565b91908281039261012084126101de576040519161127c83611020565b8294825167ffffffffffffffff81116101de57830182601f820112156101de576040916112b284836020601f19955191016111c0565b865201126101de576112f7906040516112ca81610f83565b6112d6602085016111f6565b81526112e4604085016111f6565b6020820152602085015260608301611219565b604083015261130860a0820161124f565b606083015261131960c0820161124f565b608083015260e08101519081151582036101de576101009160a084015201519060028210156101de5760c00152565b51906fffffffffffffffffffffffffffffffff821682036101de57565b91908260609103126101de5760405161137d81611004565b604080829461138b81611348565b8452602081015160208501520151910152565b9190610180838203126101de57604051906113b882610fcc565b819380519167ffffffffffffffff83116101de57610140826113e18360a09661124a9601611260565b86526113f08360208301611365565b60208701526114028360808301611365565b604087015261141360e08201611348565b6060870152611426836101008301611219565b608087015201611219565b61143d918101906110d9565b61146c8151517f0000000000000000000000000000000000000000000000000000000000000000808214611189565b60208151015180518101906020818303126101de5760208101519167ffffffffffffffff83116101de576114a792602080920192010161139e565b906114b1826118b3565b6114ba82611946565b916003831015610c1257826115ec57908167ffffffffffffffff6020604060a06110d6960193845184848201511685600354851c168111611564575b505001516040516115498161153b858201948591909160408060608301946fffffffffffffffffffffffffffffffff8151168452602081015160208501520151910152565b03601f19810183528261103c565b51902092510151165f52600560205260405f20555b51611a03565b6115a3866115e593511667ffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006003541617600355565b7fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff6fffffffffffffffff00000000000000006003549260401b16911617600355565b5f806114f6565b5060018203611631576110d690680100000000000000007fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff600454161760045561155e565b60028214611642576110d69061155e565b5050600290565b67ffffffffffffffff165f52600560205260405f205480156116685790565b7f5b48b457000000000000000000000000000000000000000000000000000000005f5260045ffd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156101de570180359067ffffffffffffffff82116101de576020019181360383136101de57565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156101de570180359067ffffffffffffffff82116101de57602001918160051b360383136101de57565b67ffffffffffffffff8111610f9f5760051b60200190565b80518210156117615760209160051b010190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b335f9081527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e0602052604090205460ff16156117c657565b7fe2517d3f000000000000000000000000000000000000000000000000000000005f52336004527fbd893629a699470e4ec82a5715bb4981fdaacc5d0a728bf5f55b801d8f4ef10b60245260445ffd5b805f525f60205260405f2073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f2054161561184d5750565b7fe2517d3f000000000000000000000000000000000000000000000000000000005f523360045260245260445ffd5b15611885575050565b7f6d23e8a3000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b611944906118d981516fffffffffffffffffffffffffffffffff606084015116906126e8565b61193c67ffffffffffffffff602060808185015160405161192e8161153b868201948591909160408060608301946fffffffffffffffffffffffffffffffff8151168452602081015160208501520151910152565b519020940151015116611649565b80821461187c565b565b67ffffffffffffffff602060a08301510151165f52600560205260405f205480155f146119735750505f90565b604082019081516040516119bc8161153b60208201948591909160408060608301946fffffffffffffffffffffffffffffffff8151168452602081015160208501520151910152565b51902014918215926119da575b5050156119d557600190565b600290565b6fffffffffffffffffffffffffffffffff91925060208291015151169151511611155f806119c9565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169080516040602083015192015192803b156101de575f92611a9b92611aad604051968795869485947f41493c600000000000000000000000000000000000000000000000000000000086526004860152606060248601526064850190610df8565b90600319848303016044850152610df8565b03915afa8015611ac857611abe5750565b5f6119449161103c565b6040513d5f823e3d90fd5b805f525f60205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260ff60405f205416155f14611b9f57805f525f60205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260405f2060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905573ffffffffffffffffffffffffffffffffffffffff339216907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d5f80a4600190565b50505f90565b805f525f60205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260ff60405f2054165f14611b9f57805f525f60205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260405f207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00815416905573ffffffffffffffffffffffffffffffffffffffff339216907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b5f80a4600190565b3567ffffffffffffffff811681036101de5790565b929190611c8e81611735565b93611c9c604051958661103c565b602085838152019160051b8101918383116101de5781905b838210611cc2575050505050565b813567ffffffffffffffff81116101de57602091611ce387849387016110bb565b815201910190611cb4565b9094929193948015612568578101906020818303126101de5780359067ffffffffffffffff82116101de57016040818303126101de5760405191611d3183610f83565b813560028110156101de578352602082013567ffffffffffffffff81116101de57611d5c92016110bb565b90602081019182528051611d6f8161105f565b611d788161105f565b611fe5575051908151820160208101926020818303126101de57602081015167ffffffffffffffff81116101de570190608090829003126101de5760405192611dc084610f83565b602082015167ffffffffffffffff81116101de5782611de9836020604094611df1970101612a5a565b865201611365565b9460208301958652611e288351517f0000000000000000000000000000000000000000000000000000000000000000808214611189565b6020835101519182518301926020818503126101de5760208101519067ffffffffffffffff82116101de5701926040848203126101de5760405193611e6c85610f83565b6020810151855260408101519167ffffffffffffffff83116101de57611e99926020809201920101612ac0565b94611eb360208501968088525180151580611fd957612c0d565b5f805b87518051831015611fa657611ece83611ee19261174d565b5151611edb368888611c82565b90612da9565b15611f9c57508694611f40611f55956fffffffffffffffffffffffffffffffff9a9895611f3961155e966020633b9aca009f9d8198611f20915161174d565b51015190815181518082149182611f88575b5050612c4b565b6001612c99565b51950194611f4d86611c6d565b875191612e1b565b516001815111611f69575b50505151160490565b611f75611f8192611c6d565b90848451511691612eab565b5f80611f60565b909150898401209089830120145f80611f32565b9060010190611eb6565b5061155e92506020915094611f40611f55956fffffffffffffffffffffffffffffffff9a9895633b9aca009c9a98612c99565b5061ffff811115612c0d565b94906001869593949551611ff88161105f565b6120018161105f565b146120485760ff86516120138161105f565b61201c8161105f565b7fd3a2e6c9000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b90919293945051926060602060405161206081610f83565b60405161206c81610fcc565b60405161207881611020565b84815260405161208781610f83565b5f81525f858201528482015260405161209f81610f83565b5f81525f8582015260408201525f858201525f60808201525f60a08201525f60c082015281526120cd612a22565b838201526120d9612a22565b60408201525f848201526040516120ef81610f83565b5f81525f84820152608082015260405161210881610f83565b5f81525f8482015260a08201528152015283518401936020818603126101de5760208101519067ffffffffffffffff82116101de5701936020858203126101de576040519461215686610fe8565b60208101519067ffffffffffffffff82116101de57602061217f92816121ac9501920101612a5a565b808652517f0000000000000000000000000000000000000000000000000000000000000000808214611189565b602084510151948551860160208101966020818303126101de57602081015167ffffffffffffffff81116101de570190604090829003126101de57604051966121f488610f83565b602082015167ffffffffffffffff81116101de578160206122179285010161139e565b885260408201519167ffffffffffffffff83116101de5761223b9201602001612ac0565b9361225560208801958087525180151580611fd957612c0d565b602081019561226387611c6d565b67ffffffffffffffff60a08a5101519181602084015116918291161480612549575b61228e85611c6d565b9267ffffffffffffffff6122a18c611c6d565b91511691156124fb57505050506122bc9061155e89516118b3565b6122c68751611946565b6003811015610c1257806124ca57506122de86611c6d565b67ffffffffffffffff8060035460401c16911611612477575b506040865101516040516123408161153b60208201948591909160408060608301946fffffffffffffffffffffffffffffffff8151168452602081015160208501520151910152565b51902067ffffffffffffffff61235587611c6d565b165f52600560205260405f20555b5f805b8551805183101561244c57611ece8361237e9261174d565b156124425750633b9aca0096936fffffffffffffffffffffffffffffffff9693611f39879460206123b56123cd9660409b5161174d565b5101519081518151808214918261242c575050612c4b565b6123f48351858101519067ffffffffffffffff602060a08185015193015101511690612e1b565b51600181511161240a575b505051015151160490565b61241661242592611c6d565b90858585510151511691612eab565b5f806123ff565b9091506020840120906020830120145f80611f32565b9060010190612366565b5060409592506123cd9150936fffffffffffffffffffffffffffffffff9693633b9aca009895612c99565b6124836124b891611c6d565b67ffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006003541617600355565b6124c46115a386611c6d565b5f6122f7565b6001915003612363577f59bc8fd3000000000000000000000000000000000000000000000000000000005f5260045ffd5b6084945067ffffffffffffffff9081604051957fb8d8167e00000000000000000000000000000000000000000000000000000000875216600486015216602484015260448301526064820152fd5b5061255384611c6d565b67ffffffffffffffff80845116911614612285565b5050909161257b60206125909201611c6d565b916040519461258986610f83565b3691611c82565b8352602083019182526040516125af8161153b86602083019586612954565b5190205c9151905182156125c9575050633b9aca00900490565b9061261d61260b926040519384937ff06fc33b000000000000000000000000000000000000000000000000000000008552604060048601526044850190610e1d565b90600319848303016024850152610df8565b0390fd5b905f8091602081519101845af480806126d5575b156126555750506040513d81523d5f602083013e60203d82010160405290565b1561269c5773ffffffffffffffffffffffffffffffffffffffff907f9996b315000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b3d156126ad576040513d5f823e3d90fd5b7fd6bda275000000000000000000000000000000000000000000000000000000005f5260045ffd5b503d1515806126355750813b1515612635565b906fffffffffffffffffffffffffffffffff633b9aca00911604428111612925578042034281116128f857610708106128c9575080515161272a600154610e75565b14806128a2575b815190156128625750602081015160ff815116906002549160ff8316928382149283612849575b6020015160ff169215612801575050505063ffffffff606082015116906004549163ffffffff83168082036127d357505063ffffffff608081920151169160201c168082036127a5575050565b7f1eb5c1eb000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b7f73b1bde3000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b6084945060ff90604051947fd382033a000000000000000000000000000000000000000000000000000000008652600486015260081c16602484015260448301526064820152fd5b6020810151600883901c60ff9081169116149350612758565b61261d906040519182917ff6b6676b0000000000000000000000000000000000000000000000000000000083526040600484015261260b60448401610ec6565b508051602081519101206040516128bc8161059a81610ec6565b6020815191012014612731565b7f12e74add000000000000000000000000000000000000000000000000000000005f524260045260245260445ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b7f20daedb6000000000000000000000000000000000000000000000000000000005f524260045260245260445ffd5b9067ffffffffffffffff90939293168152604060208201526080810190835191604080830152825180915260a0820190602060a08260051b8501019401915f905b8282106129d9575050505060206110d6939401519060607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc082850301910152610df8565b90919294602080612a14837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6089600196030186528951610df8565b970192019201909291612995565b60405190612a2f82611004565b5f6040838281528260208201520152565b9080601f830112156101de5781516110d6926020016111c0565b91906060838203126101de5760405190612a7382611004565b819380518352602081015167ffffffffffffffff81116101de5782612a99918301612a40565b602084015260408101519167ffffffffffffffff83116101de5760409261124a9201612a40565b9080601f830112156101de57815191612ad883611735565b92612ae6604051948561103c565b80845260208085019160051b830101918383116101de5760208101915b838310612b1257505050505090565b825167ffffffffffffffff81116101de578201906040601f1983880301126101de5760405190612b4182610f83565b602083015167ffffffffffffffff81116101de5760209084010187601f820112156101de578051612b7181611735565b91612b7f604051938461103c565b81835260208084019260051b820101918a83116101de5760208201905b838210612bdf5750505050825260408301519167ffffffffffffffff83116101de57612bd088602080969581960101612a40565b83820152815201920191612b03565b815167ffffffffffffffff81116101de57602091612c028e848094880101612a40565b815201910190612b9c565b15612c155750565b7fb0369c31000000000000000000000000000000000000000000000000000000005f52600452600160245261ffff60445260645ffd5b91909115612c57575050565b9061261d61260b926040519384937f5f1ca381000000000000000000000000000000000000000000000000000000008552604060048601526044850190610df8565b91909115612ca5575050565b604051907ffef760c700000000000000000000000000000000000000000000000000000000825280602483016020600485015252604482019260448260051b84010191815f907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603015b838310612d1e5786860387fd5b90919293947fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc8782030188528535828112156101de578301906020823592019167ffffffffffffffff81116101de5780360383136101de57602082601f19601f8480600198869897879852868601375f85828601015201160101970198019301919096939296612d11565b908151815103611b9f575f5b8251811015612e1357612dc8818461174d565b5151612dd4828461174d565b515103612e0c57612de5818461174d565b5160208151910120612df7828461174d565b516020815191012003612e0c57600101612db5565b5050505f90565b505050600190565b91612e7060209261193c60405185810190612e678161153b888591909160408060608301946fffffffffffffffffffffffffffffffff8151168452602081015160208501520151910152565b51902091611649565b0151808203612e7d575050565b7f4b2dfe98000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b929190925f5b8451811015612ee9578083612ec86001938861174d565b51604051612edf8161153b60208201948986612954565b5190205d01612eb1565b505050905056fea164736f6c634300081c000a","sourceMap":"1355:25496:38:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1355:25496:38;;;;;;;;4960:23;;;;1355:25496;;;;;;4960:23;1355:25496;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4960:23;1355:25496;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;4960:23;-1:-1:-1;;4960:23:38;;;;;;:::i;:::-;1355:25496;;;;;4960:23;1355:25496;;4960:23;1355:25496;;;;:::i;:::-;;;;;;;;;;;;;-1:-1:-1;;1355:25496:38;;;;;;;;1648:48;1355:25496;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;9619:70;;1355:25496;;;26731:42;26727:105;;1355:25496;9619:70;;;;:::i;:::-;9699:196;9720:30;;1355:25496;9759:25;9720:64;;;9699:196;:::i;:::-;1355:25496;9982:30;;:43;;1355:25496;;9971:95;;1355:25496;9971:95;;1355:25496;;;;;;;;;9971:95;;1355:25496;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;19046:18;1355:25496;;;;19066:11;;;:::i;:::-;19282:29;1355:25496;;;;;;;;19271:41;;;1355:25496;;;;;;;;;;;;;;;;;;;;;;;19271:41;;;;1355:25496;;19271:41;:::i;:::-;1355:25496;19261:52;;19381:21;;1355:25496;19381:36;1355:25496;;;19359:59;;;:::i;:::-;19428:179;;19449:54;;;;19428:179;:::i;:::-;19811:29;1355:25496;;;;;;;;19800:41;;;1355:25496;;;;;;;;;;;;;;;;;;;;;;;19800:41;;;;1355:25496;;19800:41;:::i;:::-;1355:25496;19790:52;;19910:21;;1355:25496;19910:36;1355:25496;;;19888:59;;;:::i;:::-;19957:179;;19978:54;;;;19957:179;:::i;:::-;10139:30;;;;:::i;:::-;1355:25496;;;;;;;;;26727:105;26800:20;;:::i;:::-;26727:105;;1355:25496;;;;;;;;;;;4723:26:84;1355:25496:38;;;:::i;:::-;4693:18:84;2484:4;4693:18;;3877:6;1355:25496:38;3877:6:84;1355:25496:38;;3877:22:84;1355:25496:38;3877:6:84;1355:25496:38;3877:22:84;1355:25496:38;3786:120:84;;4693:18;2484:4;:::i;:::-;4723:26;:::i;:::-;1355:25496:38;;;;;;-1:-1:-1;;1355:25496:38;;;;;;;;1551:51;1355:25496;;;;;;;;-1:-1:-1;;1355:25496:38;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;:::i;:::-;2095:51;1355:25496;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;2095:51;1355:25496;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;-1:-1:-1;;1355:25496:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;;1355:25496:38;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;-1:-1:-1;;1355:25496:38;;;:::i;:::-;;;;;;;;;;1526:13:116;;;1355:25496:38;1558:3:116;1541:15;;;;;;1347:26;1355:25496:38;1590:75:116;1355:25496:38;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1355:25496:38;;;;;;:::i;:::-;1627:4:116;1590:75;:::i;:::-;1577:88;;;;:::i;:::-;;;;;;:::i;:::-;;1355:25496:38;1526:13:116;;1541:15;1355:25496:38;;;;;;;;;;1541:15:116;1355:25496:38;:::i;:::-;;;;;;;;;;;;;;;;;;-1:-1:-1;;1355:25496:38;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;2930:29:84;1355:25496:38;-1:-1:-1;1355:25496:38;;;;;;-1:-1:-1;1355:25496:38;;;;;;;;;;;;;;;;-1:-1:-1;;1355:25496:38;;;;;;;;;;;;;;;;-1:-1:-1;;1355:25496:38;;;;;;;;;;;;;;;;;;;;;;;;;26731:42;26727:105;;1355:25496;7188:10;;;;;;;;:::i;:::-;:21;;;1355:25496;;;7253:10;;;;7241:64;7253:10;;:::i;:::-;7265:16;1355:25496;7294:10;7283:9;;;;;;:::i;:::-;7294:10;;;;:::i;:::-;1355:25496;;;:::i;:::-;7265:16;;7241:64;;:::i;:::-;1355:25496;;;;;;;;;;;;;26727:105;26800:20;;:::i;:::-;26727:105;;1355:25496;;;;;-1:-1:-1;;1355:25496:38;;;;;;;;2576:33;1355:25496;;;;;;;;-1:-1:-1;;1355:25496:38;;;;;;;;;;;;;;;;-1:-1:-1;;1355:25496:38;;;;;;;;;;;;;;;;;;;;;;;;;;;7544:63;;1355:25496;;;;26731:42;26727:105;;1355:25496;7586:9;7556:10;;;;:::i;:::-;7586:9;;;;;;;;:::i;:::-;1355:25496;;;7568:16;1355:25496;;;;;;;:::i;:::-;;;;7568:16;7544:63;;:::i;26727:105::-;26800:20;;:::i;:::-;26727:105;;1355:25496;;;;;;;:::i;:::-;735:10:112;1355:25496:38;;;5397:34:84;5393:102;;5505:37;;;:::i;5393:102::-;5454:30;1355:25496:38;5454:30:84;1355:25496:38;;5454:30:84;1355:25496:38;;;;;-1:-1:-1;;1355:25496:38;;;;;;;;1854:50;1355:25496;;;;;;;4306:25:84;1355:25496:38;;;:::i;:::-;4276:18:84;2484:4;4276:18;;3877:6;1355:25496:38;3877:6:84;1355:25496:38;;3877:22:84;1355:25496:38;3877:6:84;1355:25496:38;3877:22:84;1355:25496:38;3786:120:84;;2484:4;4306:25;:::i;1355:25496:38:-;;;;;-1:-1:-1;;1355:25496:38;;;;;;;;2472:10;1355:25496;;;;;;;;-1:-1:-1;;1355:25496:38;;;;;;;;;3877:6:84;1355:25496:38;3877:6:84;1355:25496:38;;3877:22:84;1355:25496:38;3877:6:84;1355:25496:38;3877:22:84;1355:25496:38;3786:120:84;;1355:25496:38;;;;;-1:-1:-1;;1355:25496:38;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;5401:1560;;1355:25496;;;26731:42;26727:105;;5401:1560;:::i;:::-;1355:25496;;;;;;;;;;;;;;;;;;;;;;;26727:105;26800:20;;:::i;:::-;5401:1560;:::i;1355:25496::-;;;;;-1:-1:-1;;1355:25496:38;;;;;;;;;1950:38;1355:25496;;;;;;;;;-1:-1:-1;;1355:25496:38;;;;;;;;1742:66;1355:25496;;;;;;;;-1:-1:-1;;1355:25496:38;;;;;;;;;;;;;;;;2649:47:84;2664:32;1355:25496:38;2649:47:84;;:87;;;;;1355:25496:38;;;;;;;2649:87:84;844:25:124;829:40;;;2649:87:84;;;1355:25496:38;;;-1:-1:-1;;1355:25496:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;-1:-1:-1;;1355:25496:38;;;;;;;;;;;;;;;;;;;:::o;:::-;;-1:-1:-1;;1355:25496:38;;;;;;;;;;;;;;;;;-1:-1:-1;1355:25496:38;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1355:25496:38;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;-1:-1:-1;;1355:25496:38;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;2095:51;1355:25496;;;;;;;:::i;:::-;;;;;2095:51;1355:25496;;;2095:51;;;;1355:25496;;;;;;;:::o;:::-;2095:51;-1:-1:-1;1355:25496:38;;;;;-1:-1:-1;1355:25496:38;;-1:-1:-1;1355:25496:38;;;;;;;;;;;;;;:::o;:::-;2095:51;1355:25496;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;:::o;:::-;;-1:-1:-1;1355:25496:38;;;;;-1:-1:-1;1355:25496:38;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;1355:25496:38;;;;;;;;;;;;;;;;:::o;:::-;;-1:-1:-1;1355:25496:38;;;:::o;:::-;;;;;;;;-1:-1:-1;;1355:25496:38;;;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;-1:-1:-1;1355:25496:38;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;-1:-1:-1;1355:25496:38;;;;;;:::o;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1355:25496:38;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;:::i;5401:1560::-;5644:58;5401:1560;5644:58;;;;:::i;:::-;5712:186;5733:24;;1355:25496;5766:26;5733:59;;;5712:186;:::i;:::-;5985:37;:24;;:37;;1355:25496;;5974:89;;1355:25496;5985:37;1355:25496;;;;;;5985:37;5974:89;;1355:25496;;;;;;;;5974:89;5985:37;5974:89;;;1355:25496;;;;:::i;:::-;6108:6;;;;:::i;:::-;6171:26;;;:::i;:::-;1355:25496;;;;;;;6211:52;;;6344:16;;1355:25496;5985:37;1355:25496;6344:16;6899:24;6344:16;;;;;:31;;;;1355:25496;;;;;;;;6344:73;;6340:155;;6207:666;6586:24;;;;1355:25496;;6575:36;;;;;;;;1355:25496;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6575:36;;-1:-1:-1;;6575:36:38;;;;;;:::i;:::-;1355:25496;6565:47;;6530:16;;:31;1355:25496;;-1:-1:-1;1355:25496:38;6508:21;5985:37;1355:25496;;-1:-1:-1;1355:25496:38;;6207:666;6899:24;;:::i;6340:155::-;1355:25496;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6340:155;;;;6207:666;-1:-1:-1;1355:25496:38;6633:58;;1355:25496;;6899:24;1355:25496;;;6707:20;1355:25496;;;6707:20;1355:25496;6207:666;;6629:244;6771:34;6755:50;;6751:122;;6899:24;6629:244;6207:666;;6751:122;6821:41;;6771:34;6821:41;:::o;5036:228::-;1355:25496;;-1:-1:-1;1355:25496:38;5145:21;1355:25496;;;-1:-1:-1;1355:25496:38;;5200:9;;1355:25496;;5036:228;:::o;1355:25496::-;;-1:-1:-1;1355:25496:38;;-1:-1:-1;1355:25496:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;3175:103:84;735:10:112;2930:6:84;1355:25496:38;;;;;;;;;;;;3495:23:84;3491:108;;3175:103::o;3491:108::-;3541:47;2930:6;3541:47;735:10:112;3541:47:84;1355:25496:38;2576:33;1355:25496;;;2930:6:84;3541:47;3175:103;1355:25496:38;2930:6:84;1355:25496:38;2930:6:84;1355:25496:38;;;2930:6:84;1355:25496:38;;735:10:112;1355:25496:38;-1:-1:-1;1355:25496:38;;;;;-1:-1:-1;1355:25496:38;;;3495:23:84;3491:108;;3175:103;:::o;3491:108::-;3541:47;2930:6;3541:47;735:10:112;3541:47:84;1355:25496:38;;;;2930:6:84;3541:47;1355:25496:38;;;;;;:::o;:::-;;;;;;;;;;;18217:570;18605:175;18217:570;18383:11;18363:18;;1355:25496;18383:11;;;1355:25496;;18383:11;;:::i;:::-;18537:58;1355:25496;18462:28;18559:20;18462:28;;;;1355:25496;;18451:40;;;;;;;;1355:25496;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18451:40;1355:25496;18441:51;;18559:20;;;:35;1355:25496;;18537:58;:::i;:::-;18626:52;;;18605:175;:::i;:::-;18217:570::o;22962:1028::-;1355:25496;23184:31;:16;;;;:31;1355:25496;;;;23162:21;23184:31;1355:25496;;;;;23230:32;;23226:758;23230:32;;;23350:43;;1355:25496;23350:43;:::o;23226:758::-;1355:25496;23470:24;;;;;1355:25496;;23459:36;;;23184:31;23459:36;;;;1355:25496;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23459:36;1355:25496;23449:47;;23427:69;;;;:165;;;23226:758;-1:-1:-1;;23410:574:38;;;23768:42;23761:49;:::o;23410:574::-;23939:34;23932:41;:::o;23427:165::-;1355:25496;23516:28;;;23184:31;23516:28;;;;1355:25496;;23558:24;;1355:25496;;-1:-1:-1;23516:76:38;23427:165;;;;24151:152;1355:25496;24231:8;1355:25496;;;;24284:11;24264:18;;;;24284:11;;;24231:65;;;;;;-1:-1:-1;1355:25496:38;;;;24284:11;1355:25496;24231:65;;;;;;;1355:25496;24231:65;;;;;1355:25496;;;;;;;;;;;:::i;:::-;;-1:-1:-1;;1355:25496:38;;;;;;;;;:::i;:::-;24231:65;;;;;;;;;;24151:152;:::o;24231:65::-;-1:-1:-1;24231:65:38;;;:::i;:::-;24284:11;1355:25496;;-1:-1:-1;1355:25496:38;;;;;6155:316:84;1355:25496:38;;;;;;;;;;;;-1:-1:-1;1355:25496:38;;;;;-1:-1:-1;1355:25496:38;;;6252:23:84;6248:217;1355:25496:38;;;;;;;;;;;;;;;-1:-1:-1;1355:25496:38;;;;-1:-1:-1;1355:25496:38;6323:4:84;1355:25496:38;;;;;;;;735:10:112;1355:25496:38;;6346:40:84;;1355:25496:38;6346:40:84;;6323:4;6400:11;:::o;6248:217::-;6442:12;;1355:25496:38;6442:12:84;:::o;6708:317::-;1355:25496:38;;;;;;;;;;;;-1:-1:-1;1355:25496:38;;;;;-1:-1:-1;1355:25496:38;;;6802:217:84;1355:25496:38;;;;;;;;;;;;;;;-1:-1:-1;1355:25496:38;;;;-1:-1:-1;1355:25496:38;;;;;;;;735:10:112;1355:25496:38;;6900:40:84;;1355:25496:38;6900:40:84;;1355:25496:38;6954:11:84;:::o;1355:25496:38:-;;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;8191:1064;;;;;;;8421:17;;8417:181;;8665:52;;1355:25496;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;8731:83;;8876:21;;1355:25496;;;10929:60;;1355:25496;10929:60;;1355:25496;;;;;;;;;10929:60;;1355:25496;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;10999:160;11020:14;;1355:25496;11043:23;11020:46;;;10999:160;:::i;:::-;1355:25496;11242:14;;:27;;1355:25496;;;11231:75;;1355:25496;;;;;;;;;11231:75;;1355:25496;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;11231:75;1355:25496;11231:75;;;1355:25496;;;;:::i;:::-;;11316:177;1355:25496;;;;;;;;11337:25;;;:70;;;11316:177;:::i;:::-;1355:25496;;11663:3;11640:14;;1355:25496;;11636:25;;;;;11703:17;;11691:43;11703:17;;:::i;:::-;;:22;1355:25496;;;;;:::i;:::-;11691:43;;:::i;:::-;11690:44;11686:99;;11824:14;;;12132:50;12335:14;11824;1355:25496;11824:14;;;11865:185;12280:27;11824:14;1355:25496;26385:3;11824:14;;;;:17;:14;;:17;:::i;:::-;;:23;;1355:25496;;;;;11894:30;;;:72;;;;11663:3;11865:185;;;:::i;:::-;1355:25496;12132:50;:::i;:::-;1355:25496;12252:26;;;;;;:::i;:::-;12280:27;;;;:::i;12335:14::-;12464;1355:25496;;;12464:25;12460:152;;11616:503;12651:27;;;1355:25496;;;8830:81;:::o;12460:152::-;12519:26;12505:96;12519:26;;:::i;:::-;12563:27;;;;1355:25496;;12505:96;;:::i;:::-;12460:152;;;;11894:72;1355:25496;;;;;;11928:16;1355:25496;;;;11948:18;11928:38;11894:72;;;;11686:99;11758:8;1355:25496;;11621:13;;;11636:25;;12280:27;11636:25;;1355:25496;11636:25;;;12132:50;12335:14;11636:25;1355:25496;11636:25;;;26385:3;11636:25;;;12132:50;:::i;11337:70::-;11366:41;1355:25496;11366:41;;;11316:177;:::i;8727:421::-;1355:25496;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;8932:98;8928:220;;1355:25496;8727:421;1355:25496;;;;:::i;:::-;;;;:::i;:::-;9188:60;1355:25496;9188:60;1355:25496;9188:60;1355:25496;;;9188:60;8928:220;9102:21;;;;;;;1355:25496;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;-1:-1:-1;1355:25496:38;;-1:-1:-1;1355:25496:38;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;1355:25496:38;;-1:-1:-1;1355:25496:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;1355:25496:38;;-1:-1:-1;1355:25496:38;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;1355:25496:38;;-1:-1:-1;1355:25496:38;;;;;;;;;;;;;;13696:75;;1355:25496;;;;;;;;;13696:75;;1355:25496;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;13696:75;;13785:208;13696:75;;1355:25496;;;;:::i;:::-;;;;;13833:41;13810:64;;;13785:208;:::i;:::-;1355:25496;14028:14;;:27;;1355:25496;;;14017:95;;1355:25496;14017:95;;1355:25496;;;;;;;;;14017:95;;1355:25496;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;14126:189;1355:25496;;;;;;;;14151:25;;;:70;;;14126:189;:::i;:::-;1355:25496;14355:26;;;;;;:::i;:::-;1355:25496;;14385:25;;:35;;:50;;1355:25496;14385:50;;1355:25496;;;;;;14355:80;:184;;;8928:220;14598:26;;;:::i;:::-;14646;1355:25496;14646:26;;;:::i;:::-;1355:25496;;;;;;;14897:25;;;;14954:14;14897:25;;;;;:::i;14954:14::-;15080:45;15099:25;;15080:45;:::i;:::-;1355:25496;;;;;;15143:52;;;15284:26;;;;:::i;:::-;1355:25496;;;;;;;;;15284:68;15280:153;;15139:599;15543:25;1355:25496;15543:25;;:43;;1355:25496;;15532:55;;;1355:25496;15532:55;;;;1355:25496;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15532:55;1355:25496;15522:66;;1355:25496;15472:26;;;:::i;:::-;1355:25496;;;15450:21;1355:25496;;;;;;15139:599;1355:25496;;15927:3;15904:14;;1355:25496;;15900:25;;;;;15967:17;;15955:43;15967:17;;:::i;15955:43::-;15954:44;15950:99;;16088:14;26385:3;16088:14;;1355:25496;16088:14;;16129:185;16088:14;;1355:25496;16088:17;16396:50;16088:14;1355:25496;16088:14;;:17;:::i;:::-;;:23;;1355:25496;;;;;16158:30;;;:72;;;;16129:185;;;:::i;16396:50::-;16632:43;16506:25;;:43;;;;:48;1355:25496;;;16506:48;;;1355:25496;16568:35;;;:50;1355:25496;;16632:43;;:::i;:::-;16799:14;1355:25496;;;16799:25;16795:198;;15880:503;17032:25;;;:43;;1355:25496;;;9046:91;:::o;16795:198::-;16871:26;16840:142;16871:26;;:::i;:::-;16915:25;;;;;:43;;1355:25496;;16840:142;;:::i;:::-;16795:198;;;;16158:72;1355:25496;;;;;;16192:16;1355:25496;;;;16212:18;16192:38;16158:72;;;;15950:99;16022:8;1355:25496;;15885:13;;;15900:25;;1355:25496;15900:25;;;16396:50;15900:25;;;1355:25496;15900:25;;26385:3;15900:25;;16396:50;:::i;15280:153::-;1355:25496;;;;:::i;:::-;;;;;;;;;;;;;;;;:::i;:::-;15280:153;;;15139:599;1355:25496;;;15613:58;15139:599;15609:129;15698:25;1355:25496;15698:25;;1355:25496;15698:25;1355:25496;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14355:184;14459:26;;;;:::i;:::-;1355:25496;;;;;;;14459:80;14355:184;;8417:181;8522:26;;;;;;1355:25496;8522:26;;;:::i;:::-;1355:25496;;;;;;;:::i;:::-;;;;:::i;:::-;;;8522:26;8550:35;;1355:25496;;;;;25522:31;;;;8522:26;25522:31;;;;;:::i;:::-;1355:25496;25512:42;;4288:69:121;25671:11:38;;25684:12;;25632:14;;1355:25496;;8489:98;;26385:3;8489:98;1355:25496;8482:105;:::o;1355:25496::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;-1:-1:-1;;1355:25496:38;;;;;;;;;:::i;:::-;;;;4691:549:110;;-1:-1:-1;4691:549:110;;3490:129:115;;;;;;;;;;4874:72:110;;4691:549;4870:364;;;4774:252:115;;;;;;;;-1:-1:-1;3490:129:115;4774:252;;;3490:129;4774:252;;;;;;4962:32:110;:::o;4870:364::-;5011:223;;;1355:25496:38;5045:24:110;;-1:-1:-1;5045:24:110;1355:25496:38;5045:24:110;1355:25496:38;;-1:-1:-1;5045:24:110;5011:223;4536:73:115;5090:33:110;4536:73:115;;1355:25496:38;;;-1:-1:-1;1355:25496:38;;;;;5086:148:110;5204:19;-1:-1:-1;5204:19:110;;-1:-1:-1;5204:19:110;4874:72;-1:-1:-1;4536:73:115;4886:33:110;;;4874:72;4886:59;4923:18;;;:22;;4874:72;;20400:2140:38;;1355:25496;26385:3;20400:2140;1355:25496;;20608:15;20583:40;;1355:25496;;20608:15;;1355:25496;20608:15;1355:25496;;;;2472:10;-1:-1:-1;1355:25496:38;;21386:25;;;1355:25496;;21429:11;1355:25496;;:::i;:::-;21380:76;:180;;;20400:2140;21611:25;;1355:25496;;;;21678:28;;;;;1355:25496;;;;;21720:22;1355:25496;;;;;21678:74;;;;:172;;;;20400:2140;21678:28;22062:40;1355:25496;;;;;;;22157:32;;;;1355:25496;22157:32;;;1355:25496;;;22193:26;1355:25496;;;;;22157:62;;;1355:25496;;22358:33;;1355:25496;22358:33;;;;1355:25496;;;21678:28;1355:25496;;22358:64;;;1355:25496;;20400:2140;;:::o;1355:25496::-;;-1:-1:-1;1355:25496:38;22193:26;1355:25496;;;;-1:-1:-1;1355:25496:38;;;-1:-1:-1;1355:25496:38;22193:26;1355:25496;;;;-1:-1:-1;1355:25496:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21678:172;:28;21772:40;;1355:25496;;;;;;;;;;;21772:78;;-1:-1:-1;21678:172:38;;1355:25496;;;;;;;;;;;;;;;;;;;;;:::i;21380:180::-;21492:25;;;1355:25496;;;;;21476:43;1355:25496;;;;;;;:::i;:::-;;;;;;21523:37;21476:84;21380:180;;1355:25496;;-1:-1:-1;1355:25496:38;20608:15;1355:25496;;;;;-1:-1:-1;1355:25496:38;;;-1:-1:-1;1355:25496:38;;;;;-1:-1:-1;1355:25496:38;;;-1:-1:-1;1355:25496:38;20608:15;1355:25496;;;;;-1:-1:-1;1355:25496:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;1355:25496:38;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;-1:-1:-1;;1355:25496:38;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::o;:::-;;;;;;8961:69;1355:25496;;14284:16;1355:25496;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1355:25496:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1355:25496:38;;;;;;;;;;;;;;;-1:-1:-1;1355:25496:38;;;;;;;;;;;;;;;;;;;;;;;;358:427:47;;1355:25496:38;;;;452:20:47;448:63;;1355:25496:38;554:3:47;1355:25496:38;;540:12:47;;;;;577:4;;;;:::i;:::-;;1355:25496:38;592:4:47;;;;:::i;:::-;;1355:25496:38;577:26:47;573:77;;677:4;;;;:::i;:::-;;1355:25496:38;;;;;667:15:47;696:4;;;;:::i;:::-;;1355:25496:38;;;;;686:15:47;667:34;663:85;;1355:25496:38;;525:13:47;;663:85;721:12;;;1355:25496:38;721:12:47;:::o;540:::-;;;;1355:25496:38;358:427:47;:::o;17339:759:38:-;;17732:177;17609:33;17339:759;17688:34;1355:25496;;17609:33;;;;;;;;;1355:25496;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17609:33;1355:25496;17599:44;;17688:34;;:::i;17732:177::-;17965:26;1355:25496;17941:50;;;1355:25496;;17339:759;;:::o;1355:25496::-;;-1:-1:-1;1355:25496:38;;;;;;-1:-1:-1;1355:25496:38;24776:318;;;;;24914:1;24937:3;1355:25496;;24917:18;;;;;25011:10;;;1355:25496;25011:10;;;:::i;:::-;;1355:25496;;24987:35;;;;;;;;;;:::i;:::-;1355:25496;24977:46;;4520:68:121;1355:25496:38;24902:13;;24917:18;;;;;;24776:318::o","linkReferences":{},"immutableReferences":{"6424":[{"start":1367,"length":32},{"start":5189,"length":32}],"6427":[{"start":505,"length":32},{"start":7681,"length":32}],"6430":[{"start":3251,"length":32},{"start":8581,"length":32}],"6433":[{"start":672,"length":32},{"start":2753,"length":32}],"6437":[{"start":3192,"length":32},{"start":6682,"length":32}]}},"methodIdentifiers":{"ALLOWED_SP1_CLOCK_DRIFT()":"2c3ee474","DEFAULT_ADMIN_ROLE()":"a217fddf","MEMBERSHIP_PROGRAM_VKEY()":"e45a6d0d","MISBEHAVIOUR_PROGRAM_VKEY()":"314d4dff","PROOF_SUBMITTER_ROLE()":"5972185a","UPDATE_CLIENT_AND_MEMBERSHIP_PROGRAM_VKEY()":"0225293e","UPDATE_CLIENT_PROGRAM_VKEY()":"ca7242f9","VERIFIER()":"08c84e70","clientState()":"bd3ce6b0","getClientState()":"ef913a4b","getConsensusStateHash(uint64)":"23842fb8","getRoleAdmin(bytes32)":"248a9ca3","grantRole(bytes32,address)":"2f2ff15d","hasRole(bytes32,address)":"91d14854","misbehaviour(bytes)":"ddba6537","multicall(bytes[])":"ac9650d8","renounceRole(bytes32,address)":"36568abe","revokeRole(bytes32,address)":"d547741f","supportsInterface(bytes4)":"01ffc9a7","updateClient(bytes)":"0bece356","verifyMembership((bytes,(uint64,uint64),bytes[],bytes))":"682ed5f0","verifyNonMembership((bytes,(uint64,uint64),bytes[]))":"4d6d9ffb"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"updateClientProgramVkey\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"membershipProgramVkey\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"updateClientAndMembershipProgramVkey\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"misbehaviourProgramVkey\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"sp1Verifier\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_clientState\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"_consensusState\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"roleManager\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotHandleMisbehavior\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"expected\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"actual\",\"type\":\"string\"}],\"name\":\"ChainIdMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"expected\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"actual\",\"type\":\"bytes\"}],\"name\":\"ClientStateMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConsensusStateHashMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConsensusStateNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConsensusStateRootMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyValue\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FeatureNotSupported\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FrozenClientState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidMembershipProof\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"path\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"value\",\"type\":\"bytes\"}],\"name\":\"KeyValuePairNotInCache\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"LengthIsOutOfRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"path\",\"type\":\"bytes[]\"}],\"name\":\"MembershipProofKeyNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"expected\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"actual\",\"type\":\"bytes\"}],\"name\":\"MembershipProofValueMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"expectedRevisionNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"expectedRevisionHeight\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"actualRevisionNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"actualRevisionHeight\",\"type\":\"uint64\"}],\"name\":\"ProofHeightMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"now\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"proofTimestamp\",\"type\":\"uint256\"}],\"name\":\"ProofIsInTheFuture\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"now\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"proofTimestamp\",\"type\":\"uint256\"}],\"name\":\"ProofIsTooOld\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expectedNumerator\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expectedDenominator\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualNumerator\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualDenominator\",\"type\":\"uint256\"}],\"name\":\"TrustThresholdMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"TrustingPeriodMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"trustingPeriod\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unbondingPeriod\",\"type\":\"uint256\"}],\"name\":\"TrustingPeriodTooLong\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"UnbondingPeriodMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"proofType\",\"type\":\"uint8\"}],\"name\":\"UnknownMembershipProofType\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"algorithm\",\"type\":\"uint8\"}],\"name\":\"UnknownZkAlgorithm\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"VerificationKeyMismatch\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ALLOWED_SP1_CLOCK_DRIFT\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MEMBERSHIP_PROGRAM_VKEY\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MISBEHAVIOUR_PROGRAM_VKEY\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PROOF_SUBMITTER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"UPDATE_CLIENT_AND_MEMBERSHIP_PROGRAM_VKEY\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"UPDATE_CLIENT_PROGRAM_VKEY\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VERIFIER\",\"outputs\":[{\"internalType\":\"contract ISP1Verifier\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"clientState\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"chainId\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"numerator\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"denominator\",\"type\":\"uint8\"}],\"internalType\":\"struct IICS07TendermintMsgs.TrustThreshold\",\"name\":\"trustLevel\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revisionNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revisionHeight\",\"type\":\"uint64\"}],\"internalType\":\"struct IICS02ClientMsgs.Height\",\"name\":\"latestHeight\",\"type\":\"tuple\"},{\"internalType\":\"uint32\",\"name\":\"trustingPeriod\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"unbondingPeriod\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isFrozen\",\"type\":\"bool\"},{\"internalType\":\"enum IICS07TendermintMsgs.SupportedZkAlgorithm\",\"name\":\"zkAlgorithm\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getClientState\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"revisionHeight\",\"type\":\"uint64\"}],\"name\":\"getConsensusStateHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"misbehaviourMsg\",\"type\":\"bytes\"}],\"name\":\"misbehaviour\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"name\":\"multicall\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"results\",\"type\":\"bytes[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"updateMsg\",\"type\":\"bytes\"}],\"name\":\"updateClient\",\"outputs\":[{\"internalType\":\"enum ILightClientMsgs.UpdateResult\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"proof\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revisionNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revisionHeight\",\"type\":\"uint64\"}],\"internalType\":\"struct IICS02ClientMsgs.Height\",\"name\":\"proofHeight\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"path\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"value\",\"type\":\"bytes\"}],\"internalType\":\"struct ILightClientMsgs.MsgVerifyMembership\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"verifyMembership\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"proof\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revisionNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revisionHeight\",\"type\":\"uint64\"}],\"internalType\":\"struct IICS02ClientMsgs.Height\",\"name\":\"proofHeight\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"path\",\"type\":\"bytes[]\"}],\"internalType\":\"struct ILightClientMsgs.MsgVerifyNonMembership\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"verifyNonMembership\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"srdtrk\",\"errors\":{\"AccessControlBadConfirmation()\":[{\"details\":\"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\"}],\"AccessControlUnauthorizedAccount(address,bytes32)\":[{\"details\":\"The `account` is missing a role.\"}],\"AddressEmptyCode(address)\":[{\"details\":\"There's no code at `target` (it is not a contract).\"}],\"CannotHandleMisbehavior()\":[{\"details\":\"Misbehavior cannot be handled in membership handler, so it is returned as an error.\"}],\"ChainIdMismatch(string,string)\":[{\"params\":{\"actual\":\"The actual chain ID.\",\"expected\":\"The expected chain ID.\"}}],\"ClientStateMismatch(bytes,bytes)\":[{\"params\":{\"actual\":\"The actual client state.\",\"expected\":\"The expected client state.\"}}],\"ConsensusStateHashMismatch(bytes32,bytes32)\":[{\"params\":{\"actual\":\"The actual consensus state hash.\",\"expected\":\"The expected consensus state hash.\"}}],\"ConsensusStateRootMismatch(bytes32,bytes32)\":[{\"params\":{\"actual\":\"The actual consensus state root.\",\"expected\":\"The expected consensus state root.\"}}],\"FailedCall()\":[{\"details\":\"A call to an address target failed. The target may have reverted.\"}],\"KeyValuePairNotInCache(bytes[],bytes)\":[{\"params\":{\"path\":\"The path of the key-value pair.\",\"value\":\"The value of the key-value pair.\"}}],\"LengthIsOutOfRange(uint256,uint256,uint256)\":[{\"params\":{\"length\":\"The length of the value.\",\"max\":\"The maximum length of the value.\",\"min\":\"The minimum length of the value.\"}}],\"MembershipProofKeyNotFound(bytes[])\":[{\"params\":{\"path\":\"The path of the key-value pair.\"}}],\"MembershipProofValueMismatch(bytes,bytes)\":[{\"params\":{\"actual\":\"The actual value.\",\"expected\":\"The expected value.\"}}],\"ProofHeightMismatch(uint64,uint64,uint64,uint64)\":[{\"params\":{\"actualRevisionHeight\":\"The actual revision height.\",\"actualRevisionNumber\":\"The actual revision number.\",\"expectedRevisionHeight\":\"The expected revision height.\",\"expectedRevisionNumber\":\"The expected revision number.\"}}],\"ProofIsInTheFuture(uint256,uint256)\":[{\"params\":{\"now\":\"The current timestamp in seconds.\",\"proofTimestamp\":\"The timestamp in the proof in seconds.\"}}],\"ProofIsTooOld(uint256,uint256)\":[{\"params\":{\"now\":\"The current timestamp in seconds.\",\"proofTimestamp\":\"The timestamp in the proof in seconds.\"}}],\"TrustThresholdMismatch(uint256,uint256,uint256,uint256)\":[{\"params\":{\"actualDenominator\":\"The actual denominator of the trust threshold.\",\"actualNumerator\":\"The actual numerator of the trust threshold.\",\"expectedDenominator\":\"The expected denominator of the trust threshold.\",\"expectedNumerator\":\"The expected numerator of the trust threshold.\"}}],\"TrustingPeriodMismatch(uint256,uint256)\":[{\"params\":{\"actual\":\"The actual trusting period in seconds.\",\"expected\":\"The expected trusting period in seconds.\"}}],\"TrustingPeriodTooLong(uint256,uint256)\":[{\"params\":{\"trustingPeriod\":\"The trusting period in seconds.\",\"unbondingPeriod\":\"The unbonding period in seconds.\"}}],\"UnbondingPeriodMismatch(uint256,uint256)\":[{\"params\":{\"actual\":\"The actual unbonding period in seconds.\",\"expected\":\"The expected unbonding period in seconds.\"}}],\"UnknownMembershipProofType(uint8)\":[{\"params\":{\"proofType\":\"The unknown membership proof type.\"}}],\"UnknownZkAlgorithm(uint8)\":[{\"params\":{\"algorithm\":\"The unknown zk algorithm.\"}}],\"VerificationKeyMismatch(bytes32,bytes32)\":[{\"params\":{\"actual\":\"The actual verification key.\",\"expected\":\"The expected verification key.\"}}]},\"events\":{\"RoleAdminChanged(bytes32,bytes32,bytes32)\":{\"details\":\"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted to signal this.\"},\"RoleGranted(bytes32,address,address)\":{\"details\":\"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call. This account bears the admin role (for the granted role). Expected in cases where the role was granted using the internal {AccessControl-_grantRole}.\"},\"RoleRevoked(bytes32,address,address)\":{\"details\":\"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)\"}},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_clientState\":\"The encoded initial client state.\",\"_consensusState\":\"The encoded initial consensus state.\",\"membershipProgramVkey\":\"The verification key for the verify (non)membership program.\",\"misbehaviourProgramVkey\":\"The verification key for the misbehaviour program.\",\"roleManager\":\"Manages the proof submitters and can submit proofs. Should be the ICS26Router if used in IBC.\",\"sp1Verifier\":\"The address of the SP1 verifier contract.\",\"updateClientAndMembershipProgramVkey\":\"The verification key for the update client and membership program.\",\"updateClientProgramVkey\":\"The verification key for the update client program.\"}},\"getClientState()\":{\"returns\":{\"_0\":\"The client state.\"}},\"getConsensusStateHash(uint64)\":{\"params\":{\"revisionHeight\":\"The revision height.\"},\"returns\":{\"_0\":\"The consensus state at the given revision height.\"}},\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"misbehaviour(bytes)\":{\"details\":\"The misbehavior is verfied in the sp1 program. Here we only check the public values which contain the trusted headers.\",\"params\":{\"misbehaviourMsg\":\"The misbehaviour message\"}},\"multicall(bytes[])\":{\"custom:oz-upgrades-unsafe-allow-reachable\":\"delegatecall\",\"details\":\"Receives and executes a batch of function calls on this contract.\"},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event.\"},\"supportsInterface(bytes4)\":{\"details\":\"Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas.\"},\"updateClient(bytes)\":{\"details\":\"This function verifies the public values and forwards the proof to the SP1 verifier.\",\"params\":{\"updateMsg\":\"The encoded update message e.g., an SP1 proof.\"},\"returns\":{\"_0\":\"The result of the update operation\"}},\"verifyMembership((bytes,(uint64,uint64),bytes[],bytes))\":{\"details\":\"Notice that this message is not view, as it may update the client state for caching purposes.\",\"params\":{\"msg_\":\"The membership message\"},\"returns\":{\"_0\":\"The unix timestamp of the verification height in the counterparty chain in seconds.\"}},\"verifyNonMembership((bytes,(uint64,uint64),bytes[]))\":{\"details\":\"Notice that this message is not view, as it may update the client state for caching purposes.\",\"params\":{\"msg_\":\"The membership message\"},\"returns\":{\"_0\":\"The unix timestamp of the verification height in the counterparty chain in seconds.\"}}},\"stateVariables\":{\"ALLOWED_SP1_CLOCK_DRIFT\":{\"return\":\"The allowed prover clock drift in seconds.\",\"returns\":{\"_0\":\"The allowed prover clock drift in seconds.\"}},\"MEMBERSHIP_PROGRAM_VKEY\":{\"return\":\"The verification key for the membership program.\",\"returns\":{\"_0\":\"The verification key for the membership program.\"}},\"MISBEHAVIOUR_PROGRAM_VKEY\":{\"return\":\"The verification key for the misbehaviour program.\",\"returns\":{\"_0\":\"The verification key for the misbehaviour program.\"}},\"PROOF_SUBMITTER_ROLE\":{\"details\":\"The proof submitter role is used to whitelist addresses that can submit proofsIf `address(0)` has this role, then anyone can submit proofsIf this client is hooked up to ICS26Router, the router must be given this role\",\"return\":\"The role identifier\",\"returns\":{\"_0\":\"The role identifier\"}},\"UPDATE_CLIENT_AND_MEMBERSHIP_PROGRAM_VKEY\":{\"return\":\"The verification key for the update client and membership program.\",\"returns\":{\"_0\":\"The verification key for the update client and membership program.\"}},\"UPDATE_CLIENT_PROGRAM_VKEY\":{\"return\":\"The verification key for the update client program.\",\"returns\":{\"_0\":\"The verification key for the update client program.\"}},\"VERIFIER\":{\"return\":\"The SP1 verifier contract.\",\"returns\":{\"_0\":\"The SP1 verifier contract.\"}},\"_consensusStateHashes\":{\"details\":\"Revision number need not be keyed as it is not allowed to change.\"}},\"title\":\"SP1 ICS07 Tendermint Light Client\",\"version\":1},\"userdoc\":{\"errors\":{\"CannotHandleMisbehavior()\":[{\"notice\":\"The error that is returned when the update client and membership program contains misbehavior.\"}],\"ChainIdMismatch(string,string)\":[{\"notice\":\"The error that is returned when the chain ID does not match the expected value.\"}],\"ClientStateMismatch(bytes,bytes)\":[{\"notice\":\"The error that is returned when the client state does not match the expected value.\"}],\"ConsensusStateHashMismatch(bytes32,bytes32)\":[{\"notice\":\"The error that is returned when the consensus state hash does not match the expected value.\"}],\"ConsensusStateNotFound()\":[{\"notice\":\"The error that is returned when the consensus state is not found.\"}],\"ConsensusStateRootMismatch(bytes32,bytes32)\":[{\"notice\":\"The error that is returned when the consensus state root does not match the expected value.\"}],\"EmptyValue()\":[{\"notice\":\"Returned when the membership value is empty.\"}],\"FeatureNotSupported()\":[{\"notice\":\"Returned when the feature is not supported.\"}],\"FrozenClientState()\":[{\"notice\":\"The error that is returned when the client state is frozen.\"}],\"InvalidMembershipProof()\":[{\"notice\":\"Returned when the membership proof is invalid.\"}],\"KeyValuePairNotInCache(bytes[],bytes)\":[{\"notice\":\"Returned when a key-value pair is not in the cache.\"}],\"LengthIsOutOfRange(uint256,uint256,uint256)\":[{\"notice\":\"The error that is returned when the length of a value is out of range.\"}],\"MembershipProofKeyNotFound(bytes[])\":[{\"notice\":\"The error that is returned when the key-value pair's path is not contained in the proof.\"}],\"MembershipProofValueMismatch(bytes,bytes)\":[{\"notice\":\"The error that is returned when the key-value pair's value does not match the expected value.\"}],\"ProofHeightMismatch(uint64,uint64,uint64,uint64)\":[{\"notice\":\"The error that is returned when the proof height does not match the expected value.\"}],\"ProofIsInTheFuture(uint256,uint256)\":[{\"notice\":\"The error that is returned when a proof is in the future.\"}],\"ProofIsTooOld(uint256,uint256)\":[{\"notice\":\"The error that is returned when a proof is too old.\"}],\"TrustThresholdMismatch(uint256,uint256,uint256,uint256)\":[{\"notice\":\"The error that is returned when the trust threshold does not match the expected value.\"}],\"TrustingPeriodMismatch(uint256,uint256)\":[{\"notice\":\"The error that is returned when the trusting period does not match the expected value.\"}],\"TrustingPeriodTooLong(uint256,uint256)\":[{\"notice\":\"The error that is returned when the trusting period is longer than the unbonding period.\"}],\"UnbondingPeriodMismatch(uint256,uint256)\":[{\"notice\":\"The error that is returned when the unbonding period does not match the expected value.\"}],\"UnknownMembershipProofType(uint8)\":[{\"notice\":\"The error that is returned when the membership proof type is unknown.\"}],\"UnknownZkAlgorithm(uint8)\":[{\"notice\":\"The error that is returned when the zk algorithm is unknown.\"}],\"VerificationKeyMismatch(bytes32,bytes32)\":[{\"notice\":\"The error that is returned when the verification key does not match the expected value.\"}]},\"kind\":\"user\",\"methods\":{\"ALLOWED_SP1_CLOCK_DRIFT()\":{\"notice\":\"Constant allowed prover clock drift in seconds.\"},\"MEMBERSHIP_PROGRAM_VKEY()\":{\"notice\":\"Immutable membership program verification key.\"},\"MISBEHAVIOUR_PROGRAM_VKEY()\":{\"notice\":\"Immutable misbehaviour program verification key.\"},\"PROOF_SUBMITTER_ROLE()\":{\"notice\":\"The role identifier for the proof submitter role\"},\"UPDATE_CLIENT_AND_MEMBERSHIP_PROGRAM_VKEY()\":{\"notice\":\"Immutable update client and membership program verification key.\"},\"UPDATE_CLIENT_PROGRAM_VKEY()\":{\"notice\":\"Immutable update client program verification key.\"},\"VERIFIER()\":{\"notice\":\"Immutable SP1 verifier contract address.\"},\"clientState()\":{\"notice\":\"The ICS07Tendermint client state\"},\"constructor\":{\"notice\":\"The constructor sets the program verification key and the initial client and consensus states.\"},\"getClientState()\":{\"notice\":\"Returns the client state.\"},\"getConsensusStateHash(uint64)\":{\"notice\":\"Returns the consensus state keccak256 hash at the given revision height.\"},\"misbehaviour(bytes)\":{\"notice\":\"Misbehaviour handling, moves the light client to the frozen state if misbehaviour is detected\"},\"updateClient(bytes)\":{\"notice\":\"Updating the client and consensus state\"},\"verifyMembership((bytes,(uint64,uint64),bytes[],bytes))\":{\"notice\":\"Querying the membership of a key-value pair\"},\"verifyNonMembership((bytes,(uint64,uint64),bytes[]))\":{\"notice\":\"Querying the non-membership of a key\"}},\"notice\":\"This contract implements an ICS07 IBC tendermint light client using SP1.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/light-clients/sp1-ics07/SP1ICS07Tendermint.sol\":\"SP1ICS07Tendermint\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[\":@openzeppelin-contracts/=node_modules/@openzeppelin/contracts/\",\":@openzeppelin-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/=node_modules/@openzeppelin/\",\":@sp1-contracts/=node_modules/sp1-contracts/contracts/src/\",\":@uniswap/permit2/=node_modules/@uniswap/permit2/\",\":forge-std/=node_modules/forge-std/src/\",\":sp1-contracts/=node_modules/sp1-contracts/\"],\"viaIR\":true},\"sources\":{\"contracts/interfaces/ILightClient.sol\":{\"keccak256\":\"0x1caae9e4f741a86c0056d5f7713a35f3bd96db7a9fd52fc9f1cf79aad76a442f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4a536db3b926560f69547c17e4f451a2631ddea0f42bd224c7fd8382d74429f6\",\"dweb:/ipfs/QmcQ33kxcmmowXgMbQGTBgiKBjF7v8UiP4y73bB9hhDizC\"]},\"contracts/light-clients/sp1-ics07/SP1ICS07Tendermint.sol\":{\"keccak256\":\"0x2e03f0f1e058e7184ea70dc2a423a3d32a609620b6a1e8b764ec9c287b0b6187\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9e3c0b2f3b3af9cfc8a3ab085e0decffcd40230a27530142293f0b79a4aefe51\",\"dweb:/ipfs/Qmf3qEAMWdiGAMEXSae6mzZ7Sncsbr4QzDC4JzMeiNwgei\"]},\"contracts/light-clients/sp1-ics07/errors/ISP1ICS07TendermintErrors.sol\":{\"keccak256\":\"0xe1a0526f9913308f761af480ef7d87091d6038659b9058f89c50083d49768db1\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a31d6d4a059182b3dfd3e99595d82a134963c448c9152ef35b42c62ccca87635\",\"dweb:/ipfs/QmfQ2Cfa4kxWem3f88o9UnFQgL8oRU6vKkDFWSGmLsVLqN\"]},\"contracts/light-clients/sp1-ics07/interfaces/ISP1ICS07Tendermint.sol\":{\"keccak256\":\"0x0f00aea96b194d1a9db14f708f0de1fe7723fedc7b72bb8ea182e768ffc0a731\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://3111a76ebabf4b57917e93669892df895a54a93a4963e384d8c13a1c47877b44\",\"dweb:/ipfs/QmPCZ7Z4dJpowkzMhizUAW1j8QdJLD3DDjMbYq8G5VeXc1\"]},\"contracts/light-clients/sp1-ics07/msgs/IICS07TendermintMsgs.sol\":{\"keccak256\":\"0xae0ae6ff2742192ebaaee297c7d7473a1e1b4dc73393d45a944b0b7a8a647703\",\"license\":\"UNLICENSED\",\"urls\":[\"bzz-raw://43b2f6492a1f727416bbcf55876d9c08ac1f66f4724efc75b935c5022555be20\",\"dweb:/ipfs/QmfTaPFNSFuUEsEBgJjnF2Jr2knayS7YwatfjP7dgdcAyH\"]},\"contracts/light-clients/sp1-ics07/msgs/IMembershipMsgs.sol\":{\"keccak256\":\"0x9dff6833fddbc11caf27387c9f8cba5dca9d1e430c9643d4e4a2e8eb09924d96\",\"license\":\"UNLICENSED\",\"urls\":[\"bzz-raw://efa6cfc654510dfcef6f4286e3e66446082bcd5671662ae6e1c6fd0f893a5a4a\",\"dweb:/ipfs/QmRWAg1kHvmRtXgDm4ajVC7tEWQnzTWmHeHMYQJfyFuDGq\"]},\"contracts/light-clients/sp1-ics07/msgs/IMisbehaviourMsgs.sol\":{\"keccak256\":\"0x165b37d890b06eccd47558bf1efd6495e18541627758736a1f5b9c33d0333832\",\"license\":\"UNLICENSED\",\"urls\":[\"bzz-raw://15ab15cd5439147abed697bc9644b0175754845608bf3d57c81c2c864d31ce46\",\"dweb:/ipfs/QmYcV88YsM1sZCmhP8LKUFHq3hJ6bsvd66W5axBnsBBoUM\"]},\"contracts/light-clients/sp1-ics07/msgs/ISP1Msgs.sol\":{\"keccak256\":\"0x8ede29b02182df4be9c075b3b48083277e5dd93bb3e7ce1eecfea9728db49aed\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://48edb4bbcd440454fffceb4f85b83c08c3973a212239d7da07c079634fe413dd\",\"dweb:/ipfs/Qmf7ma1nXWghfZKrJJvLpPuY5aN2xZZjHY7kWP3KVFCoDJ\"]},\"contracts/light-clients/sp1-ics07/msgs/IUcAndMembershipMsgs.sol\":{\"keccak256\":\"0xef3619c79de37cabe95d9d8af9d145fc2ea2dd55137407fb4b0082b0491170d0\",\"license\":\"UNLICENSED\",\"urls\":[\"bzz-raw://93646d813cdacf5e38e609e54baa67c60d749f0f111d00cd18b003c3cb328204\",\"dweb:/ipfs/QmVcuwPujbiZ644a4jRw2V1LZxhhGsm2HKMXweVqndwUnZ\"]},\"contracts/light-clients/sp1-ics07/msgs/IUpdateClientMsgs.sol\":{\"keccak256\":\"0x370cdfca1c65f1898c7da80507e66972a6fe51a5d5c4e7aeabdd7060ce875aed\",\"license\":\"UNLICENSED\",\"urls\":[\"bzz-raw://ff34288a142b6f40d6843818b9ec0a542db016bc0d4a7be582eb2e255655c43e\",\"dweb:/ipfs/QmXwbJHDbqZdw3JTT48Le1ZWGqmKAG7omf2ePvDfBHomzj\"]},\"contracts/light-clients/sp1-ics07/utils/Paths.sol\":{\"keccak256\":\"0x0e4eec6cd6cd0ef684383946419a2bf53c8f800033acfc298db81688e5aa178b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://824b58c13ff96b6ee38b5d25435fcc1305c45735f52df6347dba3dacdc144ffa\",\"dweb:/ipfs/QmT7qomKM46ChfVVwfBQHwjpoHW9vrG9nXkGXsPeZRLJ7w\"]},\"contracts/msgs/IICS02ClientMsgs.sol\":{\"keccak256\":\"0xb5fdb25319d5c32b3f527982d45ec1e9bec5215515581aee034d853006ea01a0\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6b8939bf552c62c952a491008bcd9b59ab7dda20a9482bf93438e05793881542\",\"dweb:/ipfs/QmfWmzNCp8bd4pP26Lfw5HHp4dSZnCDqZDjVN7SD8P7eDh\"]},\"contracts/msgs/ILightClientMsgs.sol\":{\"keccak256\":\"0xa0565e7748b8b3284d72e1aa6ef4cc8264fcaa5f4e0761d22d64686953db6378\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c4476010d7090bfaa74127526f2051c6bc82ff42a09b936e848880a1f15a6065\",\"dweb:/ipfs/QmY87JgRsFQXSZdGXNjNHEJCkdTHzFXH4vZEJ3q7MnHuP8\"]},\"node_modules/@openzeppelin/contracts/access/AccessControl.sol\":{\"keccak256\":\"0x1a6b4f6b7798ab80929d491b89d5427a9b3338c0fd1acd0ba325f69c6f1646af\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://7bb7f346c12a14dc622bc105ce3c47202fbc89f4b153a28a63bb68193297330c\",\"dweb:/ipfs/QmagwF8P3bUBXwdo159ueEnY9dLSvEWwK24kk2op58egwG\"]},\"node_modules/@openzeppelin/contracts/access/IAccessControl.sol\":{\"keccak256\":\"0xbff9f59c84e5337689161ce7641c0ef8e872d6a7536fbc1f5133f128887aba3c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b308f882e796f7b79c9502deacb0a62983035c6f6f4e962b319ba6a1f4a77d3d\",\"dweb:/ipfs/QmaWCW7ahEQqFjwhSUhV7Ae7WhfNvzSpE7DQ58hvEooqPL\"]},\"node_modules/@openzeppelin/contracts/utils/Address.sol\":{\"keccak256\":\"0x0fa9e0d3a859900b5a46f70a03c73adf259603d5e05027a37fe0b45529d85346\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c2add4da0240c9f2ce47649c8bb6b11b40e98cf6f88b8bdc76b2704e89391710\",\"dweb:/ipfs/QmNQTwF2uVzu4CRtNxr8bxyP9XuW6VsZuo2Nr4KR2bZr3d\"]},\"node_modules/@openzeppelin/contracts/utils/Context.sol\":{\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12\",\"dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF\"]},\"node_modules/@openzeppelin/contracts/utils/Errors.sol\":{\"keccak256\":\"0x6afa713bfd42cf0f7656efa91201007ac465e42049d7de1d50753a373648c123\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ba1d02f4847670a1b83dec9f7d37f0b0418d6043447b69f3a29a5f9efc547fcf\",\"dweb:/ipfs/QmQ7iH2keLNUKgq2xSWcRmuBE5eZ3F5whYAkAGzCNNoEWB\"]},\"node_modules/@openzeppelin/contracts/utils/LowLevelCall.sol\":{\"keccak256\":\"0x5b4802a4352474792df3107e961d1cc593e47b820c14f69d3505cb28f5a6a583\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a6f86fd01f829499fe0545ff5dda07d4521988e88bfe0bf801fc15650921ed56\",\"dweb:/ipfs/QmUUKu4ZDffHAmfkf3asuQfmLTyfpuy2Amdncc3SqfzKPG\"]},\"node_modules/@openzeppelin/contracts/utils/Multicall.sol\":{\"keccak256\":\"0x72a5499dfae7676e4298a7299bccd3b27438ba1a4c72df5cd69c1c343c7ea20d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://de0fb51ccae3a0ff377ed185d187440fc612a71bf8e42fdb0e032ce747fa3eef\",\"dweb:/ipfs/QmPNBaiVsAiUhz8qfXcSy27S7CqBbtSd8rPqmaykKBhw7Q\"]},\"node_modules/@openzeppelin/contracts/utils/TransientSlot.sol\":{\"keccak256\":\"0xac673fa1e374d9e6107504af363333e3e5f6344d2e83faf57d9bfd41d77cc946\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5982478dbbb218e9dd5a6e83f5c0e8d1654ddf20178484b43ef21dd2246809de\",\"dweb:/ipfs/QmaB1hS68n2kG8vTbt7EPEzmrGhkUbfiFyykGGLsAr9X22\"]},\"node_modules/@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"keccak256\":\"0x2d9dc2fe26180f74c11c13663647d38e259e45f95eb88f57b61d2160b0109d3e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://81233d1f98060113d9922180bb0f14f8335856fe9f339134b09335e9f678c377\",\"dweb:/ipfs/QmWh6R35SarhAn4z2wH8SU456jJSYL2FgucfTFgbHJJN4E\"]},\"node_modules/@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x8891738ffe910f0cf2da09566928589bf5d63f4524dd734fd9cedbac3274dd5c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://971f954442df5c2ef5b5ebf1eb245d7105d9fbacc7386ee5c796df1d45b21617\",\"dweb:/ipfs/QmadRjHbkicwqwwh61raUEapaVEtaLMcYbQZWs9gUkgj3u\"]},\"node_modules/sp1-contracts/contracts/src/ISP1Verifier.sol\":{\"keccak256\":\"0x9e3ba64860bea920772dcf16be7946de2a2900d80bd51e9c0771184138f4f4d3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://0ec7230ca1fdd74edc6ab597d80bb345282aed3f0db4788ed96b4cc373ff46a3\",\"dweb:/ipfs/QmXPuSS5gzxMhFKWr1gsxBVu6WHh53ZZEvWkGgzrkM6Y7Q\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.28+commit.7893614a"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"bytes32","name":"updateClientProgramVkey","type":"bytes32"},{"internalType":"bytes32","name":"membershipProgramVkey","type":"bytes32"},{"internalType":"bytes32","name":"updateClientAndMembershipProgramVkey","type":"bytes32"},{"internalType":"bytes32","name":"misbehaviourProgramVkey","type":"bytes32"},{"internalType":"address","name":"sp1Verifier","type":"address"},{"internalType":"bytes","name":"_clientState","type":"bytes"},{"internalType":"bytes32","name":"_consensusState","type":"bytes32"},{"internalType":"address","name":"roleManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"type":"error","name":"AccessControlBadConfirmation"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"type":"error","name":"AccessControlUnauthorizedAccount"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"type":"error","name":"AddressEmptyCode"},{"inputs":[],"type":"error","name":"CannotHandleMisbehavior"},{"inputs":[{"internalType":"string","name":"expected","type":"string"},{"internalType":"string","name":"actual","type":"string"}],"type":"error","name":"ChainIdMismatch"},{"inputs":[{"internalType":"bytes","name":"expected","type":"bytes"},{"internalType":"bytes","name":"actual","type":"bytes"}],"type":"error","name":"ClientStateMismatch"},{"inputs":[{"internalType":"bytes32","name":"expected","type":"bytes32"},{"internalType":"bytes32","name":"actual","type":"bytes32"}],"type":"error","name":"ConsensusStateHashMismatch"},{"inputs":[],"type":"error","name":"ConsensusStateNotFound"},{"inputs":[{"internalType":"bytes32","name":"expected","type":"bytes32"},{"internalType":"bytes32","name":"actual","type":"bytes32"}],"type":"error","name":"ConsensusStateRootMismatch"},{"inputs":[],"type":"error","name":"EmptyValue"},{"inputs":[],"type":"error","name":"FailedCall"},{"inputs":[],"type":"error","name":"FeatureNotSupported"},{"inputs":[],"type":"error","name":"FrozenClientState"},{"inputs":[],"type":"error","name":"InvalidMembershipProof"},{"inputs":[{"internalType":"bytes[]","name":"path","type":"bytes[]"},{"internalType":"bytes","name":"value","type":"bytes"}],"type":"error","name":"KeyValuePairNotInCache"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"},{"internalType":"uint256","name":"min","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"type":"error","name":"LengthIsOutOfRange"},{"inputs":[{"internalType":"bytes[]","name":"path","type":"bytes[]"}],"type":"error","name":"MembershipProofKeyNotFound"},{"inputs":[{"internalType":"bytes","name":"expected","type":"bytes"},{"internalType":"bytes","name":"actual","type":"bytes"}],"type":"error","name":"MembershipProofValueMismatch"},{"inputs":[{"internalType":"uint64","name":"expectedRevisionNumber","type":"uint64"},{"internalType":"uint64","name":"expectedRevisionHeight","type":"uint64"},{"internalType":"uint64","name":"actualRevisionNumber","type":"uint64"},{"internalType":"uint64","name":"actualRevisionHeight","type":"uint64"}],"type":"error","name":"ProofHeightMismatch"},{"inputs":[{"internalType":"uint256","name":"now","type":"uint256"},{"internalType":"uint256","name":"proofTimestamp","type":"uint256"}],"type":"error","name":"ProofIsInTheFuture"},{"inputs":[{"internalType":"uint256","name":"now","type":"uint256"},{"internalType":"uint256","name":"proofTimestamp","type":"uint256"}],"type":"error","name":"ProofIsTooOld"},{"inputs":[{"internalType":"uint256","name":"expectedNumerator","type":"uint256"},{"internalType":"uint256","name":"expectedDenominator","type":"uint256"},{"internalType":"uint256","name":"actualNumerator","type":"uint256"},{"internalType":"uint256","name":"actualDenominator","type":"uint256"}],"type":"error","name":"TrustThresholdMismatch"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"actual","type":"uint256"}],"type":"error","name":"TrustingPeriodMismatch"},{"inputs":[{"internalType":"uint256","name":"trustingPeriod","type":"uint256"},{"internalType":"uint256","name":"unbondingPeriod","type":"uint256"}],"type":"error","name":"TrustingPeriodTooLong"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"actual","type":"uint256"}],"type":"error","name":"UnbondingPeriodMismatch"},{"inputs":[{"internalType":"uint8","name":"proofType","type":"uint8"}],"type":"error","name":"UnknownMembershipProofType"},{"inputs":[{"internalType":"uint8","name":"algorithm","type":"uint8"}],"type":"error","name":"UnknownZkAlgorithm"},{"inputs":[{"internalType":"bytes32","name":"expected","type":"bytes32"},{"internalType":"bytes32","name":"actual","type":"bytes32"}],"type":"error","name":"VerificationKeyMismatch"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32","indexed":true},{"internalType":"bytes32","name":"previousAdminRole","type":"bytes32","indexed":true},{"internalType":"bytes32","name":"newAdminRole","type":"bytes32","indexed":true}],"type":"event","name":"RoleAdminChanged","anonymous":false},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32","indexed":true},{"internalType":"address","name":"account","type":"address","indexed":true},{"internalType":"address","name":"sender","type":"address","indexed":true}],"type":"event","name":"RoleGranted","anonymous":false},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32","indexed":true},{"internalType":"address","name":"account","type":"address","indexed":true},{"internalType":"address","name":"sender","type":"address","indexed":true}],"type":"event","name":"RoleRevoked","anonymous":false},{"inputs":[],"stateMutability":"view","type":"function","name":"ALLOWED_SP1_CLOCK_DRIFT","outputs":[{"internalType":"uint16","name":"","type":"uint16"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"MEMBERSHIP_PROGRAM_VKEY","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"MISBEHAVIOUR_PROGRAM_VKEY","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"PROOF_SUBMITTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"UPDATE_CLIENT_AND_MEMBERSHIP_PROGRAM_VKEY","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"UPDATE_CLIENT_PROGRAM_VKEY","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"VERIFIER","outputs":[{"internalType":"contract ISP1Verifier","name":"","type":"address"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"clientState","outputs":[{"internalType":"string","name":"chainId","type":"string"},{"internalType":"struct IICS07TendermintMsgs.TrustThreshold","name":"trustLevel","type":"tuple","components":[{"internalType":"uint8","name":"numerator","type":"uint8"},{"internalType":"uint8","name":"denominator","type":"uint8"}]},{"internalType":"struct IICS02ClientMsgs.Height","name":"latestHeight","type":"tuple","components":[{"internalType":"uint64","name":"revisionNumber","type":"uint64"},{"internalType":"uint64","name":"revisionHeight","type":"uint64"}]},{"internalType":"uint32","name":"trustingPeriod","type":"uint32"},{"internalType":"uint32","name":"unbondingPeriod","type":"uint32"},{"internalType":"bool","name":"isFrozen","type":"bool"},{"internalType":"enum IICS07TendermintMsgs.SupportedZkAlgorithm","name":"zkAlgorithm","type":"uint8"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"getClientState","outputs":[{"internalType":"bytes","name":"","type":"bytes"}]},{"inputs":[{"internalType":"uint64","name":"revisionHeight","type":"uint64"}],"stateMutability":"view","type":"function","name":"getConsensusStateHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"stateMutability":"view","type":"function","name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"grantRole"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"stateMutability":"view","type":"function","name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"bytes","name":"misbehaviourMsg","type":"bytes"}],"stateMutability":"nonpayable","type":"function","name":"misbehaviour"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"stateMutability":"nonpayable","type":"function","name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}]},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"renounceRole"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"revokeRole"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"stateMutability":"view","type":"function","name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"bytes","name":"updateMsg","type":"bytes"}],"stateMutability":"nonpayable","type":"function","name":"updateClient","outputs":[{"internalType":"enum ILightClientMsgs.UpdateResult","name":"","type":"uint8"}]},{"inputs":[{"internalType":"struct ILightClientMsgs.MsgVerifyMembership","name":"msg_","type":"tuple","components":[{"internalType":"bytes","name":"proof","type":"bytes"},{"internalType":"struct IICS02ClientMsgs.Height","name":"proofHeight","type":"tuple","components":[{"internalType":"uint64","name":"revisionNumber","type":"uint64"},{"internalType":"uint64","name":"revisionHeight","type":"uint64"}]},{"internalType":"bytes[]","name":"path","type":"bytes[]"},{"internalType":"bytes","name":"value","type":"bytes"}]}],"stateMutability":"nonpayable","type":"function","name":"verifyMembership","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"struct ILightClientMsgs.MsgVerifyNonMembership","name":"msg_","type":"tuple","components":[{"internalType":"bytes","name":"proof","type":"bytes"},{"internalType":"struct IICS02ClientMsgs.Height","name":"proofHeight","type":"tuple","components":[{"internalType":"uint64","name":"revisionNumber","type":"uint64"},{"internalType":"uint64","name":"revisionHeight","type":"uint64"}]},{"internalType":"bytes[]","name":"path","type":"bytes[]"}]}],"stateMutability":"nonpayable","type":"function","name":"verifyNonMembership","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]}],"devdoc":{"kind":"dev","methods":{"constructor":{"params":{"_clientState":"The encoded initial client state.","_consensusState":"The encoded initial consensus state.","membershipProgramVkey":"The verification key for the verify (non)membership program.","misbehaviourProgramVkey":"The verification key for the misbehaviour program.","roleManager":"Manages the proof submitters and can submit proofs. Should be the ICS26Router if used in IBC.","sp1Verifier":"The address of the SP1 verifier contract.","updateClientAndMembershipProgramVkey":"The verification key for the update client and membership program.","updateClientProgramVkey":"The verification key for the update client program."}},"getClientState()":{"returns":{"_0":"The client state."}},"getConsensusStateHash(uint64)":{"params":{"revisionHeight":"The revision height."},"returns":{"_0":"The consensus state at the given revision height."}},"getRoleAdmin(bytes32)":{"details":"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}."},"grantRole(bytes32,address)":{"details":"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event."},"hasRole(bytes32,address)":{"details":"Returns `true` if `account` has been granted `role`."},"misbehaviour(bytes)":{"details":"The misbehavior is verfied in the sp1 program. Here we only check the public values which contain the trusted headers.","params":{"misbehaviourMsg":"The misbehaviour message"}},"multicall(bytes[])":{"custom:oz-upgrades-unsafe-allow-reachable":"delegatecall","details":"Receives and executes a batch of function calls on this contract."},"renounceRole(bytes32,address)":{"details":"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event."},"revokeRole(bytes32,address)":{"details":"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event."},"supportsInterface(bytes4)":{"details":"Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas."},"updateClient(bytes)":{"details":"This function verifies the public values and forwards the proof to the SP1 verifier.","params":{"updateMsg":"The encoded update message e.g., an SP1 proof."},"returns":{"_0":"The result of the update operation"}},"verifyMembership((bytes,(uint64,uint64),bytes[],bytes))":{"details":"Notice that this message is not view, as it may update the client state for caching purposes.","params":{"msg_":"The membership message"},"returns":{"_0":"The unix timestamp of the verification height in the counterparty chain in seconds."}},"verifyNonMembership((bytes,(uint64,uint64),bytes[]))":{"details":"Notice that this message is not view, as it may update the client state for caching purposes.","params":{"msg_":"The membership message"},"returns":{"_0":"The unix timestamp of the verification height in the counterparty chain in seconds."}}},"version":1},"userdoc":{"kind":"user","methods":{"ALLOWED_SP1_CLOCK_DRIFT()":{"notice":"Constant allowed prover clock drift in seconds."},"MEMBERSHIP_PROGRAM_VKEY()":{"notice":"Immutable membership program verification key."},"MISBEHAVIOUR_PROGRAM_VKEY()":{"notice":"Immutable misbehaviour program verification key."},"PROOF_SUBMITTER_ROLE()":{"notice":"The role identifier for the proof submitter role"},"UPDATE_CLIENT_AND_MEMBERSHIP_PROGRAM_VKEY()":{"notice":"Immutable update client and membership program verification key."},"UPDATE_CLIENT_PROGRAM_VKEY()":{"notice":"Immutable update client program verification key."},"VERIFIER()":{"notice":"Immutable SP1 verifier contract address."},"clientState()":{"notice":"The ICS07Tendermint client state"},"constructor":{"notice":"The constructor sets the program verification key and the initial client and consensus states."},"getClientState()":{"notice":"Returns the client state."},"getConsensusStateHash(uint64)":{"notice":"Returns the consensus state keccak256 hash at the given revision height."},"misbehaviour(bytes)":{"notice":"Misbehaviour handling, moves the light client to the frozen state if misbehaviour is detected"},"updateClient(bytes)":{"notice":"Updating the client and consensus state"},"verifyMembership((bytes,(uint64,uint64),bytes[],bytes))":{"notice":"Querying the membership of a key-value pair"},"verifyNonMembership((bytes,(uint64,uint64),bytes[]))":{"notice":"Querying the non-membership of a key"}},"version":1}},"settings":{"remappings":["@openzeppelin-contracts/=node_modules/@openzeppelin/contracts/","@openzeppelin-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/","@openzeppelin/=node_modules/@openzeppelin/","@sp1-contracts/=node_modules/sp1-contracts/contracts/src/","@uniswap/permit2/=node_modules/@uniswap/permit2/","forge-std/=node_modules/forge-std/src/","sp1-contracts/=node_modules/sp1-contracts/"],"optimizer":{"enabled":true,"runs":10000},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"contracts/light-clients/sp1-ics07/SP1ICS07Tendermint.sol":"SP1ICS07Tendermint"},"evmVersion":"cancun","libraries":{},"viaIR":true},"sources":{"contracts/interfaces/ILightClient.sol":{"keccak256":"0x1caae9e4f741a86c0056d5f7713a35f3bd96db7a9fd52fc9f1cf79aad76a442f","urls":["bzz-raw://4a536db3b926560f69547c17e4f451a2631ddea0f42bd224c7fd8382d74429f6","dweb:/ipfs/QmcQ33kxcmmowXgMbQGTBgiKBjF7v8UiP4y73bB9hhDizC"],"license":"MIT"},"contracts/light-clients/sp1-ics07/SP1ICS07Tendermint.sol":{"keccak256":"0x2e03f0f1e058e7184ea70dc2a423a3d32a609620b6a1e8b764ec9c287b0b6187","urls":["bzz-raw://9e3c0b2f3b3af9cfc8a3ab085e0decffcd40230a27530142293f0b79a4aefe51","dweb:/ipfs/Qmf3qEAMWdiGAMEXSae6mzZ7Sncsbr4QzDC4JzMeiNwgei"],"license":"MIT"},"contracts/light-clients/sp1-ics07/errors/ISP1ICS07TendermintErrors.sol":{"keccak256":"0xe1a0526f9913308f761af480ef7d87091d6038659b9058f89c50083d49768db1","urls":["bzz-raw://a31d6d4a059182b3dfd3e99595d82a134963c448c9152ef35b42c62ccca87635","dweb:/ipfs/QmfQ2Cfa4kxWem3f88o9UnFQgL8oRU6vKkDFWSGmLsVLqN"],"license":"MIT"},"contracts/light-clients/sp1-ics07/interfaces/ISP1ICS07Tendermint.sol":{"keccak256":"0x0f00aea96b194d1a9db14f708f0de1fe7723fedc7b72bb8ea182e768ffc0a731","urls":["bzz-raw://3111a76ebabf4b57917e93669892df895a54a93a4963e384d8c13a1c47877b44","dweb:/ipfs/QmPCZ7Z4dJpowkzMhizUAW1j8QdJLD3DDjMbYq8G5VeXc1"],"license":"MIT"},"contracts/light-clients/sp1-ics07/msgs/IICS07TendermintMsgs.sol":{"keccak256":"0xae0ae6ff2742192ebaaee297c7d7473a1e1b4dc73393d45a944b0b7a8a647703","urls":["bzz-raw://43b2f6492a1f727416bbcf55876d9c08ac1f66f4724efc75b935c5022555be20","dweb:/ipfs/QmfTaPFNSFuUEsEBgJjnF2Jr2knayS7YwatfjP7dgdcAyH"],"license":"UNLICENSED"},"contracts/light-clients/sp1-ics07/msgs/IMembershipMsgs.sol":{"keccak256":"0x9dff6833fddbc11caf27387c9f8cba5dca9d1e430c9643d4e4a2e8eb09924d96","urls":["bzz-raw://efa6cfc654510dfcef6f4286e3e66446082bcd5671662ae6e1c6fd0f893a5a4a","dweb:/ipfs/QmRWAg1kHvmRtXgDm4ajVC7tEWQnzTWmHeHMYQJfyFuDGq"],"license":"UNLICENSED"},"contracts/light-clients/sp1-ics07/msgs/IMisbehaviourMsgs.sol":{"keccak256":"0x165b37d890b06eccd47558bf1efd6495e18541627758736a1f5b9c33d0333832","urls":["bzz-raw://15ab15cd5439147abed697bc9644b0175754845608bf3d57c81c2c864d31ce46","dweb:/ipfs/QmYcV88YsM1sZCmhP8LKUFHq3hJ6bsvd66W5axBnsBBoUM"],"license":"UNLICENSED"},"contracts/light-clients/sp1-ics07/msgs/ISP1Msgs.sol":{"keccak256":"0x8ede29b02182df4be9c075b3b48083277e5dd93bb3e7ce1eecfea9728db49aed","urls":["bzz-raw://48edb4bbcd440454fffceb4f85b83c08c3973a212239d7da07c079634fe413dd","dweb:/ipfs/Qmf7ma1nXWghfZKrJJvLpPuY5aN2xZZjHY7kWP3KVFCoDJ"],"license":"MIT"},"contracts/light-clients/sp1-ics07/msgs/IUcAndMembershipMsgs.sol":{"keccak256":"0xef3619c79de37cabe95d9d8af9d145fc2ea2dd55137407fb4b0082b0491170d0","urls":["bzz-raw://93646d813cdacf5e38e609e54baa67c60d749f0f111d00cd18b003c3cb328204","dweb:/ipfs/QmVcuwPujbiZ644a4jRw2V1LZxhhGsm2HKMXweVqndwUnZ"],"license":"UNLICENSED"},"contracts/light-clients/sp1-ics07/msgs/IUpdateClientMsgs.sol":{"keccak256":"0x370cdfca1c65f1898c7da80507e66972a6fe51a5d5c4e7aeabdd7060ce875aed","urls":["bzz-raw://ff34288a142b6f40d6843818b9ec0a542db016bc0d4a7be582eb2e255655c43e","dweb:/ipfs/QmXwbJHDbqZdw3JTT48Le1ZWGqmKAG7omf2ePvDfBHomzj"],"license":"UNLICENSED"},"contracts/light-clients/sp1-ics07/utils/Paths.sol":{"keccak256":"0x0e4eec6cd6cd0ef684383946419a2bf53c8f800033acfc298db81688e5aa178b","urls":["bzz-raw://824b58c13ff96b6ee38b5d25435fcc1305c45735f52df6347dba3dacdc144ffa","dweb:/ipfs/QmT7qomKM46ChfVVwfBQHwjpoHW9vrG9nXkGXsPeZRLJ7w"],"license":"MIT"},"contracts/msgs/IICS02ClientMsgs.sol":{"keccak256":"0xb5fdb25319d5c32b3f527982d45ec1e9bec5215515581aee034d853006ea01a0","urls":["bzz-raw://6b8939bf552c62c952a491008bcd9b59ab7dda20a9482bf93438e05793881542","dweb:/ipfs/QmfWmzNCp8bd4pP26Lfw5HHp4dSZnCDqZDjVN7SD8P7eDh"],"license":"MIT"},"contracts/msgs/ILightClientMsgs.sol":{"keccak256":"0xa0565e7748b8b3284d72e1aa6ef4cc8264fcaa5f4e0761d22d64686953db6378","urls":["bzz-raw://c4476010d7090bfaa74127526f2051c6bc82ff42a09b936e848880a1f15a6065","dweb:/ipfs/QmY87JgRsFQXSZdGXNjNHEJCkdTHzFXH4vZEJ3q7MnHuP8"],"license":"MIT"},"node_modules/@openzeppelin/contracts/access/AccessControl.sol":{"keccak256":"0x1a6b4f6b7798ab80929d491b89d5427a9b3338c0fd1acd0ba325f69c6f1646af","urls":["bzz-raw://7bb7f346c12a14dc622bc105ce3c47202fbc89f4b153a28a63bb68193297330c","dweb:/ipfs/QmagwF8P3bUBXwdo159ueEnY9dLSvEWwK24kk2op58egwG"],"license":"MIT"},"node_modules/@openzeppelin/contracts/access/IAccessControl.sol":{"keccak256":"0xbff9f59c84e5337689161ce7641c0ef8e872d6a7536fbc1f5133f128887aba3c","urls":["bzz-raw://b308f882e796f7b79c9502deacb0a62983035c6f6f4e962b319ba6a1f4a77d3d","dweb:/ipfs/QmaWCW7ahEQqFjwhSUhV7Ae7WhfNvzSpE7DQ58hvEooqPL"],"license":"MIT"},"node_modules/@openzeppelin/contracts/utils/Address.sol":{"keccak256":"0x0fa9e0d3a859900b5a46f70a03c73adf259603d5e05027a37fe0b45529d85346","urls":["bzz-raw://c2add4da0240c9f2ce47649c8bb6b11b40e98cf6f88b8bdc76b2704e89391710","dweb:/ipfs/QmNQTwF2uVzu4CRtNxr8bxyP9XuW6VsZuo2Nr4KR2bZr3d"],"license":"MIT"},"node_modules/@openzeppelin/contracts/utils/Context.sol":{"keccak256":"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2","urls":["bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12","dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF"],"license":"MIT"},"node_modules/@openzeppelin/contracts/utils/Errors.sol":{"keccak256":"0x6afa713bfd42cf0f7656efa91201007ac465e42049d7de1d50753a373648c123","urls":["bzz-raw://ba1d02f4847670a1b83dec9f7d37f0b0418d6043447b69f3a29a5f9efc547fcf","dweb:/ipfs/QmQ7iH2keLNUKgq2xSWcRmuBE5eZ3F5whYAkAGzCNNoEWB"],"license":"MIT"},"node_modules/@openzeppelin/contracts/utils/LowLevelCall.sol":{"keccak256":"0x5b4802a4352474792df3107e961d1cc593e47b820c14f69d3505cb28f5a6a583","urls":["bzz-raw://a6f86fd01f829499fe0545ff5dda07d4521988e88bfe0bf801fc15650921ed56","dweb:/ipfs/QmUUKu4ZDffHAmfkf3asuQfmLTyfpuy2Amdncc3SqfzKPG"],"license":"MIT"},"node_modules/@openzeppelin/contracts/utils/Multicall.sol":{"keccak256":"0x72a5499dfae7676e4298a7299bccd3b27438ba1a4c72df5cd69c1c343c7ea20d","urls":["bzz-raw://de0fb51ccae3a0ff377ed185d187440fc612a71bf8e42fdb0e032ce747fa3eef","dweb:/ipfs/QmPNBaiVsAiUhz8qfXcSy27S7CqBbtSd8rPqmaykKBhw7Q"],"license":"MIT"},"node_modules/@openzeppelin/contracts/utils/TransientSlot.sol":{"keccak256":"0xac673fa1e374d9e6107504af363333e3e5f6344d2e83faf57d9bfd41d77cc946","urls":["bzz-raw://5982478dbbb218e9dd5a6e83f5c0e8d1654ddf20178484b43ef21dd2246809de","dweb:/ipfs/QmaB1hS68n2kG8vTbt7EPEzmrGhkUbfiFyykGGLsAr9X22"],"license":"MIT"},"node_modules/@openzeppelin/contracts/utils/introspection/ERC165.sol":{"keccak256":"0x2d9dc2fe26180f74c11c13663647d38e259e45f95eb88f57b61d2160b0109d3e","urls":["bzz-raw://81233d1f98060113d9922180bb0f14f8335856fe9f339134b09335e9f678c377","dweb:/ipfs/QmWh6R35SarhAn4z2wH8SU456jJSYL2FgucfTFgbHJJN4E"],"license":"MIT"},"node_modules/@openzeppelin/contracts/utils/introspection/IERC165.sol":{"keccak256":"0x8891738ffe910f0cf2da09566928589bf5d63f4524dd734fd9cedbac3274dd5c","urls":["bzz-raw://971f954442df5c2ef5b5ebf1eb245d7105d9fbacc7386ee5c796df1d45b21617","dweb:/ipfs/QmadRjHbkicwqwwh61raUEapaVEtaLMcYbQZWs9gUkgj3u"],"license":"MIT"},"node_modules/sp1-contracts/contracts/src/ISP1Verifier.sol":{"keccak256":"0x9e3ba64860bea920772dcf16be7946de2a2900d80bd51e9c0771184138f4f4d3","urls":["bzz-raw://0ec7230ca1fdd74edc6ab597d80bb345282aed3f0db4788ed96b4cc373ff46a3","dweb:/ipfs/QmXPuSS5gzxMhFKWr1gsxBVu6WHh53ZZEvWkGgzrkM6Y7Q"],"license":"MIT"}},"version":1},"id":38} \ No newline at end of file +{"abi":[{"type":"constructor","inputs":[{"name":"updateClientProgramVkey","type":"bytes32","internalType":"bytes32"},{"name":"membershipProgramVkey","type":"bytes32","internalType":"bytes32"},{"name":"updateClientAndMembershipProgramVkey","type":"bytes32","internalType":"bytes32"},{"name":"misbehaviourProgramVkey","type":"bytes32","internalType":"bytes32"},{"name":"sp1Verifier","type":"address","internalType":"address"},{"name":"_clientState","type":"bytes","internalType":"bytes"},{"name":"_consensusState","type":"bytes32","internalType":"bytes32"},{"name":"roleManager","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"ALLOWED_SP1_CLOCK_DRIFT","inputs":[],"outputs":[{"name":"","type":"uint16","internalType":"uint16"}],"stateMutability":"view"},{"type":"function","name":"DEFAULT_ADMIN_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"MEMBERSHIP_PROGRAM_VKEY","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"MISBEHAVIOUR_PROGRAM_VKEY","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"PROOF_SUBMITTER_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"UPDATE_CLIENT_AND_MEMBERSHIP_PROGRAM_VKEY","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"UPDATE_CLIENT_PROGRAM_VKEY","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"VERIFIER","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ISP1Verifier"}],"stateMutability":"view"},{"type":"function","name":"clientState","inputs":[],"outputs":[{"name":"chainId","type":"string","internalType":"string"},{"name":"trustLevel","type":"tuple","internalType":"struct IICS07TendermintMsgs.TrustThreshold","components":[{"name":"numerator","type":"uint8","internalType":"uint8"},{"name":"denominator","type":"uint8","internalType":"uint8"}]},{"name":"latestHeight","type":"tuple","internalType":"struct IICS02ClientMsgs.Height","components":[{"name":"revisionNumber","type":"uint64","internalType":"uint64"},{"name":"revisionHeight","type":"uint64","internalType":"uint64"}]},{"name":"trustingPeriod","type":"uint32","internalType":"uint32"},{"name":"unbondingPeriod","type":"uint32","internalType":"uint32"},{"name":"isFrozen","type":"bool","internalType":"bool"},{"name":"zkAlgorithm","type":"uint8","internalType":"enum IICS07TendermintMsgs.SupportedZkAlgorithm"}],"stateMutability":"view"},{"type":"function","name":"getClientState","inputs":[],"outputs":[{"name":"","type":"bytes","internalType":"bytes"}],"stateMutability":"view"},{"type":"function","name":"getConsensusStateHash","inputs":[{"name":"revisionHeight","type":"uint64","internalType":"uint64"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"getRoleAdmin","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"grantRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"hasRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"misbehaviour","inputs":[{"name":"misbehaviourMsg","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"multicall","inputs":[{"name":"data","type":"bytes[]","internalType":"bytes[]"}],"outputs":[{"name":"results","type":"bytes[]","internalType":"bytes[]"}],"stateMutability":"nonpayable"},{"type":"function","name":"renounceRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"callerConfirmation","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"revokeRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"updateClient","inputs":[{"name":"updateMsg","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"","type":"uint8","internalType":"enum ILightClientMsgs.UpdateResult"}],"stateMutability":"nonpayable"},{"type":"function","name":"verifyMembership","inputs":[{"name":"msg_","type":"tuple","internalType":"struct ILightClientMsgs.MsgVerifyMembership","components":[{"name":"proof","type":"bytes","internalType":"bytes"},{"name":"proofHeight","type":"tuple","internalType":"struct IICS02ClientMsgs.Height","components":[{"name":"revisionNumber","type":"uint64","internalType":"uint64"},{"name":"revisionHeight","type":"uint64","internalType":"uint64"}]},{"name":"path","type":"bytes[]","internalType":"bytes[]"},{"name":"value","type":"bytes","internalType":"bytes"}]}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"verifyNonMembership","inputs":[{"name":"msg_","type":"tuple","internalType":"struct ILightClientMsgs.MsgVerifyNonMembership","components":[{"name":"proof","type":"bytes","internalType":"bytes"},{"name":"proofHeight","type":"tuple","internalType":"struct IICS02ClientMsgs.Height","components":[{"name":"revisionNumber","type":"uint64","internalType":"uint64"},{"name":"revisionHeight","type":"uint64","internalType":"uint64"}]},{"name":"path","type":"bytes[]","internalType":"bytes[]"}]}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"event","name":"RoleAdminChanged","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"previousAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"newAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"error","name":"AccessControlBadConfirmation","inputs":[]},{"type":"error","name":"AccessControlUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"},{"name":"neededRole","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"AddressEmptyCode","inputs":[{"name":"target","type":"address","internalType":"address"}]},{"type":"error","name":"CannotHandleMisbehavior","inputs":[]},{"type":"error","name":"ChainIdMismatch","inputs":[{"name":"expected","type":"string","internalType":"string"},{"name":"actual","type":"string","internalType":"string"}]},{"type":"error","name":"ClientStateMismatch","inputs":[{"name":"expected","type":"bytes","internalType":"bytes"},{"name":"actual","type":"bytes","internalType":"bytes"}]},{"type":"error","name":"ConsensusStateHashMismatch","inputs":[{"name":"expected","type":"bytes32","internalType":"bytes32"},{"name":"actual","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"ConsensusStateNotFound","inputs":[]},{"type":"error","name":"ConsensusStateRootMismatch","inputs":[{"name":"expected","type":"bytes32","internalType":"bytes32"},{"name":"actual","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"EmptyValue","inputs":[]},{"type":"error","name":"FailedCall","inputs":[]},{"type":"error","name":"FeatureNotSupported","inputs":[]},{"type":"error","name":"FrozenClientState","inputs":[]},{"type":"error","name":"InvalidMembershipProof","inputs":[]},{"type":"error","name":"KeyValuePairNotInCache","inputs":[{"name":"path","type":"bytes[]","internalType":"bytes[]"},{"name":"value","type":"bytes","internalType":"bytes"}]},{"type":"error","name":"LengthIsOutOfRange","inputs":[{"name":"length","type":"uint256","internalType":"uint256"},{"name":"min","type":"uint256","internalType":"uint256"},{"name":"max","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"MembershipProofKeyNotFound","inputs":[{"name":"path","type":"bytes[]","internalType":"bytes[]"}]},{"type":"error","name":"MembershipProofValueMismatch","inputs":[{"name":"expected","type":"bytes","internalType":"bytes"},{"name":"actual","type":"bytes","internalType":"bytes"}]},{"type":"error","name":"ProofHeightMismatch","inputs":[{"name":"expectedRevisionNumber","type":"uint64","internalType":"uint64"},{"name":"expectedRevisionHeight","type":"uint64","internalType":"uint64"},{"name":"actualRevisionNumber","type":"uint64","internalType":"uint64"},{"name":"actualRevisionHeight","type":"uint64","internalType":"uint64"}]},{"type":"error","name":"ProofIsInTheFuture","inputs":[{"name":"now","type":"uint256","internalType":"uint256"},{"name":"proofTimestamp","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ProofIsTooOld","inputs":[{"name":"now","type":"uint256","internalType":"uint256"},{"name":"proofTimestamp","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"TrustThresholdMismatch","inputs":[{"name":"expectedNumerator","type":"uint256","internalType":"uint256"},{"name":"expectedDenominator","type":"uint256","internalType":"uint256"},{"name":"actualNumerator","type":"uint256","internalType":"uint256"},{"name":"actualDenominator","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"TrustingPeriodMismatch","inputs":[{"name":"expected","type":"uint256","internalType":"uint256"},{"name":"actual","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"TrustingPeriodTooLong","inputs":[{"name":"trustingPeriod","type":"uint256","internalType":"uint256"},{"name":"unbondingPeriod","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"UnbondingPeriodMismatch","inputs":[{"name":"expected","type":"uint256","internalType":"uint256"},{"name":"actual","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"UnknownMembershipProofType","inputs":[{"name":"proofType","type":"uint8","internalType":"uint8"}]},{"type":"error","name":"UnknownZkAlgorithm","inputs":[{"name":"algorithm","type":"uint8","internalType":"uint8"}]},{"type":"error","name":"VerificationKeyMismatch","inputs":[{"name":"expected","type":"bytes32","internalType":"bytes32"},{"name":"actual","type":"bytes32","internalType":"bytes32"}]}],"bytecode":{"object":"0x61012060405234610541576137268038038061001a81610564565b928339810161010082820312610541578151916020810151604082015160608301519061004960808501610589565b60a08501519095906001600160401b0381116105415785019080601f8301121561054157815161007b9260200161059d565b9261008d60e060c08701519601610589565b9660805260a05260c05260e05280518101906020820190602081840312610541576020810151906001600160401b038211610541570191829003601f1981019061012013610541576040519160e083016001600160401b0381118482101761052d5760405260208401516001600160401b038111610541576020908501019080601f830112156105415781516101259260200161059d565b825260408112610541576040610139610545565b916101458286016105dd565b8352610153606086016105dd565b602084015260208401928352603f19011261054157610170610545565b61017c608085016105eb565b815261018a60a085016105eb565b6020820152604083019081526101a260c085016105ff565b90606084019182526101b660e086016105ff565b92608085019384526101008601519586151587036105415760a0860196875261012001519460028610156105415760c08101958652518051906001600160401b03821161052d57600154600181811c91168015610523575b602082101461050f57601f81116104ac575b50602090601f831160011461043f5763ffffffff95949392915f9183610434575b50508160011b915f199060031b1c1916176001555b5160ff81511661ff00602060025493015160081b169161ffff191617176002555160018060401b0381511660035491602068010000000000000000600160801b0391015160401b169160018060801b031916171760035551169267ffffffff00000000600454925160201b169051151560401b92519160028310156104205769ff00000000000000000068ff00000000000000009360481b169469ff000000000000000000199160018060481b0319161716179116171760045560018060401b0360035460401c165f52600560205260405f205560018060a01b03166101005260045463ffffffff8116610708810163ffffffff811161040c5763ffffffff809360201c1692839116116103f757826001600160a01b0381166103de575061037c610706565b505b604051612efd908161078982396080518181816105570152611445015260a0518181816101f90152611e01015260c051818181610cb30152612185015260e0518181816102a00152610ac1015261010051818181610c780152611a1a0152f35b806103eb6103f192610610565b50610686565b5061037e565b6333fae18560e21b5f5260045260245260445ffd5b634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52602160045260245ffd5b015190505f80610241565b90601f1983169160015f52815f20925f5b818110610494575091600193918563ffffffff99989796941061047c575b505050811b01600155610256565b01515f1960f88460031b161c191690555f808061046e565b92936020600181928786015181550195019301610450565b60015f527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6601f840160051c81019160208510610505575b601f0160051c01905b8181106104fa5750610220565b5f81556001016104ed565b90915081906104e4565b634e487b7160e01b5f52602260045260245ffd5b90607f169061020e565b634e487b7160e01b5f52604160045260245ffd5b5f80fd5b60408051919082016001600160401b0381118382101761052d57604052565b6040519190601f01601f191682016001600160401b0381118382101761052d57604052565b51906001600160a01b038216820361054157565b9192916001600160401b03821161052d576105c1601f8301601f1916602001610564565b938285528282011161054157815f926020928387015e84010152565b519060ff8216820361054157565b51906001600160401b038216820361054157565b519063ffffffff8216820361054157565b6001600160a01b0381165f9081525f5160206137065f395f51905f52602052604090205460ff16610681576001600160a01b03165f8181525f5160206137065f395f51905f5260205260408120805460ff191660011790553391905f5160206136865f395f51905f528180a4600190565b505f90565b6001600160a01b0381165f9081525f5160206136a65f395f51905f52602052604090205460ff16610681576001600160a01b03165f8181525f5160206136a65f395f51905f5260205260408120805460ff191660011790553391905f5160206136e65f395f51905f52905f5160206136865f395f51905f529080a4600190565b5f80525f5160206136a65f395f51905f526020525f5160206136c65f395f51905f525460ff16610784575f8080525f5160206136a65f395f51905f526020525f5160206136c65f395f51905f52805460ff1916600117905533905f5160206136e65f395f51905f525f5160206136865f395f51905f528280a4600190565b5f9056fe6080806040526004361015610012575f80fd5b5f3560e01c90816301ffc9a714610cd6575080630225293e14610c9c57806308c84e7014610c4c5780630bece35614610b8957806323842fb814610b59578063248a9ca314610b2f5780632c3ee47414610b135780632f2ff15d14610ae4578063314d4dff14610aaa57806336568abe14610a4e5780634d6d9ffb1461096c5780635972185a14610932578063682ed5f01461080e57806391d14854146107c5578063a217fddf146107ab578063ac9650d81461066a578063bd3ce6b01461057a578063ca7242f914610540578063d547741f1461050a578063ddba65371461021c578063e45a6d0d146101e25763ef913a4b1461010e575f80fd5b346101de575f6003193601126101de576101da60405160208082015261012060408201526101c6816101436101608201610ec6565b60ff600254818116606085015260081c16608083015267ffffffffffffffff60035481811660a085015260401c1660c083015260ff60045463ffffffff811660e085015263ffffffff8160201c16610100850152818160401c16151561012085015260481c166101b28161105f565b61014083015203601f19810183528261103c565b604051918291602083526020830190610df8565b0390f35b5f80fd5b346101de575f6003193601126101de5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b346101de5761022a36610d74565b6004549160ff8360401c166104e2575f80527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e06020527f6e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac4754610298929060ff16156104d5575b8101906110d9565b6102c78151517f0000000000000000000000000000000000000000000000000000000000000000808214611189565b6020815101518051810160208101916020818303126101de57602081015167ffffffffffffffff81116101de57019061018090829003126101de576040519061030f82610fcc565b602081015167ffffffffffffffff81116101de57839082016020019061033491611260565b825261034260408201611348565b60208301908152906103578460608301611219565b604084019081529161036c8560a08401611219565b60608501908152946103818160e08501611365565b9260808601938452610140019061039791611365565b9360a081019485525190516fffffffffffffffffffffffffffffffff166103bd916126e8565b516040805182516fffffffffffffffffffffffffffffffff16602080830191825284015182840152919092015160608084019190915282529061040160808261103c565b51902090516020015167ffffffffffffffff1661041d90611649565b61042a919081811461187c565b516040805182516fffffffffffffffffffffffffffffffff16602080830191825284015182840152919092015160608084019190915282529061046e60808261103c565b51902090516020015167ffffffffffffffff1661048a90611649565b610497919081811461187c565b516104a190611a03565b7fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff1668010000000000000000176004555f80f35b6104dd61178e565b610290565b7f928b1233000000000000000000000000000000000000000000000000000000005f5260045ffd5b346101de5761053e61051b36610dc5565b90610539610534825f525f602052600160405f20015490565b611816565b611ba5565b005b346101de575f6003193601126101de5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b346101de575f6003193601126101de576040516105a18161059a81610ec6565b038261103c565b6101206040516105b081610f83565b60025460ff8116825260ff602083019160081c16815260ff6040516105d481610f83565b67ffffffffffffffff600354818116835281602084019160401c168152816004549385808660481c1697816106146040519d8d8f9e8f9081520190610df8565b9a511660208c0152511660408a0152511660608801525116608086015263ffffffff811660a086015263ffffffff8160201c1660c086015260401c16151560e08401526106608161105f565b6101008301520390f35b346101de5760206003193601126101de5760043567ffffffffffffffff81116101de57366023820112156101de57806004013567ffffffffffffffff81116101de57602482013660248360051b850101116101de5760405160206106ce818361103c565b5f825280820192601f1982013685376106e685611735565b956106f4604051978861103c565b858752601f1961070387611735565b01835f5b82811061079b575050505f5b868110156107885760019061076c61076661073660248460051b87010187611690565b9190888b846040519586948486013783018281015f81528d519283915e01015f815203601f19810183528261103c565b30612621565b610776828b61174d565b52610781818a61174d565b5001610713565b604051848152806101da8187018b610e1d565b606082828c010152018490610707565b346101de575f6003193601126101de5760206040515f8152f35b346101de576107d336610dc5565b905f525f60205273ffffffffffffffffffffffffffffffffffffffff60405f2091165f52602052602060ff60405f2054166040519015158152f35b346101de5760206003193601126101de5760043567ffffffffffffffff81116101de578060040160a060031983360301126101de5760ff60045460401c166104e2575f80527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e06020527f6e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac475460ff1615610925575b60848201916108b18383611690565b9050156108fd57602092826108c9816108f595611690565b60246108ed6108e66108de60648901876116e1565b979096611690565b3691611085565b950191611cee565b604051908152f35b7f1208b21b000000000000000000000000000000000000000000000000000000005f5260045ffd5b61092d61178e565b6108a2565b346101de575f6003193601126101de5760206040517fbd893629a699470e4ec82a5715bb4981fdaacc5d0a728bf5f55b801d8f4ef10b8152f35b346101de5760206003193601126101de5760043567ffffffffffffffff81116101de5780600401608060031983360301126101de5760ff60045460401c166104e2575f80527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e060209081527f6e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac475490926108f592909160ff1615610a41575b610a24610a178280611690565b91909260648501906116e1565b929091602460405195610a37898861103c565b5f87520191611cee565b610a4961178e565b610a0a565b346101de57610a5c36610dc5565b3373ffffffffffffffffffffffffffffffffffffffff821603610a825761053e91611ba5565b7f6697b232000000000000000000000000000000000000000000000000000000005f5260045ffd5b346101de575f6003193601126101de5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b346101de5761053e610af536610dc5565b90610b0e610534825f525f602052600160405f20015490565b611ad3565b346101de575f6003193601126101de5760206040516107088152f35b346101de5760206003193601126101de5760206108f56004355f525f602052600160405f20015490565b346101de5760206003193601126101de5760043567ffffffffffffffff811681036101de576108f5602091611649565b346101de57610b9736610d74565b60ff60045460401c166104e2575f80527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e06020527f6e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac4754610bff929060ff1615610c3f57611431565b6040516003821015610c12576020918152f35b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b610c4761178e565b611431565b346101de575f6003193601126101de57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346101de575f6003193601126101de5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b346101de5760206003193601126101de57600435907fffffffff0000000000000000000000000000000000000000000000000000000082168092036101de57817f7965db0b0000000000000000000000000000000000000000000000000000000060209314908115610d4a575b5015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501483610d43565b9060206003198301126101de5760043567ffffffffffffffff81116101de57826023820112156101de5780600401359267ffffffffffffffff84116101de57602484830101116101de576024019190565b60031960409101126101de576004359060243573ffffffffffffffffffffffffffffffffffffffff811681036101de5790565b90601f19601f602080948051918291828752018686015e5f8582860101520116010190565b9080602083519182815201916020808360051b8301019401925f915b838310610e4857505050505090565b9091929394602080610e6683601f1986600196030187528951610df8565b97019301930191939290610e39565b90600182811c92168015610ebc575b6020831014610e8f57565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b91607f1691610e84565b6001545f9291610ed582610e75565b8082529160018116908115610f495750600114610ef0575050565b60015f9081529293509091907fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65b838310610f2f575060209250010190565b600181602092949394548385870101520191019190610f1e565b60209495507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091509291921683830152151560051b010190565b6040810190811067ffffffffffffffff821117610f9f57604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b60c0810190811067ffffffffffffffff821117610f9f57604052565b6020810190811067ffffffffffffffff821117610f9f57604052565b6060810190811067ffffffffffffffff821117610f9f57604052565b60e0810190811067ffffffffffffffff821117610f9f57604052565b90601f601f19910116810190811067ffffffffffffffff821117610f9f57604052565b60021115610c1257565b67ffffffffffffffff8111610f9f57601f01601f191660200190565b92919261109182611069565b9161109f604051938461103c565b8294818452818301116101de578281602093845f960137010152565b9080601f830112156101de578160206110d693359101611085565b90565b6020818303126101de5780359067ffffffffffffffff82116101de5701906020828203126101de576040519161110e83610fe8565b80359067ffffffffffffffff82116101de57016060818303126101de576040519161113883611004565b81358352602082013567ffffffffffffffff81116101de578161115c9184016110bb565b6020840152604082013567ffffffffffffffff81116101de5761117f92016110bb565b6040820152815290565b15611192575050565b7fd56bdc26000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b9291926111cc82611069565b916111da604051938461103c565b8294818452818301116101de578281602093845f96015e010152565b519060ff821682036101de57565b519067ffffffffffffffff821682036101de57565b91908260409103126101de5760405161123181610f83565b602061124a81839561124281611204565b855201611204565b910152565b519063ffffffff821682036101de57565b91908281039261012084126101de576040519161127c83611020565b8294825167ffffffffffffffff81116101de57830182601f820112156101de576040916112b284836020601f19955191016111c0565b865201126101de576112f7906040516112ca81610f83565b6112d6602085016111f6565b81526112e4604085016111f6565b6020820152602085015260608301611219565b604083015261130860a0820161124f565b606083015261131960c0820161124f565b608083015260e08101519081151582036101de576101009160a084015201519060028210156101de5760c00152565b51906fffffffffffffffffffffffffffffffff821682036101de57565b91908260609103126101de5760405161137d81611004565b604080829461138b81611348565b8452602081015160208501520151910152565b9190610180838203126101de57604051906113b882610fcc565b819380519167ffffffffffffffff83116101de57610140826113e18360a09661124a9601611260565b86526113f08360208301611365565b60208701526114028360808301611365565b604087015261141360e08201611348565b6060870152611426836101008301611219565b608087015201611219565b61143d918101906110d9565b61146c8151517f0000000000000000000000000000000000000000000000000000000000000000808214611189565b60208151015180518101906020818303126101de5760208101519167ffffffffffffffff83116101de576114a792602080920192010161139e565b906114b1826118b3565b6114ba82611946565b916003831015610c1257826115ec57908167ffffffffffffffff6020604060a06110d6960193845184848201511685600354851c168111611564575b505001516040516115498161153b858201948591909160408060608301946fffffffffffffffffffffffffffffffff8151168452602081015160208501520151910152565b03601f19810183528261103c565b51902092510151165f52600560205260405f20555b51611a03565b6115a3866115e593511667ffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006003541617600355565b7fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff6fffffffffffffffff00000000000000006003549260401b16911617600355565b5f806114f6565b5060018203611631576110d690680100000000000000007fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff600454161760045561155e565b60028214611642576110d69061155e565b5050600290565b67ffffffffffffffff165f52600560205260405f205480156116685790565b7f5b48b457000000000000000000000000000000000000000000000000000000005f5260045ffd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156101de570180359067ffffffffffffffff82116101de576020019181360383136101de57565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156101de570180359067ffffffffffffffff82116101de57602001918160051b360383136101de57565b67ffffffffffffffff8111610f9f5760051b60200190565b80518210156117615760209160051b010190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b335f9081527f4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e0602052604090205460ff16156117c657565b7fe2517d3f000000000000000000000000000000000000000000000000000000005f52336004527fbd893629a699470e4ec82a5715bb4981fdaacc5d0a728bf5f55b801d8f4ef10b60245260445ffd5b805f525f60205260405f2073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f2054161561184d5750565b7fe2517d3f000000000000000000000000000000000000000000000000000000005f523360045260245260445ffd5b15611885575050565b7f6d23e8a3000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b611944906118d981516fffffffffffffffffffffffffffffffff606084015116906126e8565b61193c67ffffffffffffffff602060808185015160405161192e8161153b868201948591909160408060608301946fffffffffffffffffffffffffffffffff8151168452602081015160208501520151910152565b519020940151015116611649565b80821461187c565b565b67ffffffffffffffff602060a08301510151165f52600560205260405f205480155f146119735750505f90565b604082019081516040516119bc8161153b60208201948591909160408060608301946fffffffffffffffffffffffffffffffff8151168452602081015160208501520151910152565b51902014918215926119da575b5050156119d557600190565b600290565b6fffffffffffffffffffffffffffffffff91925060208291015151169151511611155f806119c9565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169080516040602083015192015192803b156101de575f92611a9b92611aad604051968795869485947f41493c600000000000000000000000000000000000000000000000000000000086526004860152606060248601526064850190610df8565b90600319848303016044850152610df8565b03915afa8015611ac857611abe5750565b5f6119449161103c565b6040513d5f823e3d90fd5b805f525f60205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260ff60405f205416155f14611b9f57805f525f60205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260405f2060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905573ffffffffffffffffffffffffffffffffffffffff339216907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d5f80a4600190565b50505f90565b805f525f60205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260ff60405f2054165f14611b9f57805f525f60205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260405f207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00815416905573ffffffffffffffffffffffffffffffffffffffff339216907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b5f80a4600190565b3567ffffffffffffffff811681036101de5790565b929190611c8e81611735565b93611c9c604051958661103c565b602085838152019160051b8101918383116101de5781905b838210611cc2575050505050565b813567ffffffffffffffff81116101de57602091611ce387849387016110bb565b815201910190611cb4565b9094929193948015612568578101906020818303126101de5780359067ffffffffffffffff82116101de57016040818303126101de5760405191611d3183610f83565b813560028110156101de578352602082013567ffffffffffffffff81116101de57611d5c92016110bb565b90602081019182528051611d6f8161105f565b611d788161105f565b611fe5575051908151820160208101926020818303126101de57602081015167ffffffffffffffff81116101de570190608090829003126101de5760405192611dc084610f83565b602082015167ffffffffffffffff81116101de5782611de9836020604094611df1970101612a5a565b865201611365565b9460208301958652611e288351517f0000000000000000000000000000000000000000000000000000000000000000808214611189565b6020835101519182518301926020818503126101de5760208101519067ffffffffffffffff82116101de5701926040848203126101de5760405193611e6c85610f83565b6020810151855260408101519167ffffffffffffffff83116101de57611e99926020809201920101612ac0565b94611eb360208501968088525180151580611fd957612c0d565b5f805b87518051831015611fa657611ece83611ee19261174d565b5151611edb368888611c82565b90612da9565b15611f9c57508694611f40611f55956fffffffffffffffffffffffffffffffff9a9895611f3961155e966020633b9aca009f9d8198611f20915161174d565b51015190815181518082149182611f88575b5050612c4b565b6001612c99565b51950194611f4d86611c6d565b875191612e1b565b516001815111611f69575b50505151160490565b611f75611f8192611c6d565b90848451511691612eab565b5f80611f60565b909150898401209089830120145f80611f32565b9060010190611eb6565b5061155e92506020915094611f40611f55956fffffffffffffffffffffffffffffffff9a9895633b9aca009c9a98612c99565b5061ffff811115612c0d565b94906001869593949551611ff88161105f565b6120018161105f565b146120485760ff86516120138161105f565b61201c8161105f565b7fd3a2e6c9000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b90919293945051926060602060405161206081610f83565b60405161206c81610fcc565b60405161207881611020565b84815260405161208781610f83565b5f81525f858201528482015260405161209f81610f83565b5f81525f8582015260408201525f858201525f60808201525f60a08201525f60c082015281526120cd612a22565b838201526120d9612a22565b60408201525f848201526040516120ef81610f83565b5f81525f84820152608082015260405161210881610f83565b5f81525f8482015260a08201528152015283518401936020818603126101de5760208101519067ffffffffffffffff82116101de5701936020858203126101de576040519461215686610fe8565b60208101519067ffffffffffffffff82116101de57602061217f92816121ac9501920101612a5a565b808652517f0000000000000000000000000000000000000000000000000000000000000000808214611189565b602084510151948551860160208101966020818303126101de57602081015167ffffffffffffffff81116101de570190604090829003126101de57604051966121f488610f83565b602082015167ffffffffffffffff81116101de578160206122179285010161139e565b885260408201519167ffffffffffffffff83116101de5761223b9201602001612ac0565b9361225560208801958087525180151580611fd957612c0d565b602081019561226387611c6d565b67ffffffffffffffff60a08a5101519181602084015116918291161480612549575b61228e85611c6d565b9267ffffffffffffffff6122a18c611c6d565b91511691156124fb57505050506122bc9061155e89516118b3565b6122c68751611946565b6003811015610c1257806124ca57506122de86611c6d565b67ffffffffffffffff8060035460401c16911611612477575b506040865101516040516123408161153b60208201948591909160408060608301946fffffffffffffffffffffffffffffffff8151168452602081015160208501520151910152565b51902067ffffffffffffffff61235587611c6d565b165f52600560205260405f20555b5f805b8551805183101561244c57611ece8361237e9261174d565b156124425750633b9aca0096936fffffffffffffffffffffffffffffffff9693611f39879460206123b56123cd9660409b5161174d565b5101519081518151808214918261242c575050612c4b565b6123f48351858101519067ffffffffffffffff602060a08185015193015101511690612e1b565b51600181511161240a575b505051015151160490565b61241661242592611c6d565b90858585510151511691612eab565b5f806123ff565b9091506020840120906020830120145f80611f32565b9060010190612366565b5060409592506123cd9150936fffffffffffffffffffffffffffffffff9693633b9aca009895612c99565b6124836124b891611c6d565b67ffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006003541617600355565b6124c46115a386611c6d565b5f6122f7565b6001915003612363577f59bc8fd3000000000000000000000000000000000000000000000000000000005f5260045ffd5b6084945067ffffffffffffffff9081604051957fb8d8167e00000000000000000000000000000000000000000000000000000000875216600486015216602484015260448301526064820152fd5b5061255384611c6d565b67ffffffffffffffff80845116911614612285565b5050909161257b60206125909201611c6d565b916040519461258986610f83565b3691611c82565b8352602083019182526040516125af8161153b86602083019586612954565b5190205c9151905182156125c9575050633b9aca00900490565b9061261d61260b926040519384937ff06fc33b000000000000000000000000000000000000000000000000000000008552604060048601526044850190610e1d565b90600319848303016024850152610df8565b0390fd5b905f8091602081519101845af480806126d5575b156126555750506040513d81523d5f602083013e60203d82010160405290565b1561269c5773ffffffffffffffffffffffffffffffffffffffff907f9996b315000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b3d156126ad576040513d5f823e3d90fd5b7fd6bda275000000000000000000000000000000000000000000000000000000005f5260045ffd5b503d1515806126355750813b1515612635565b906fffffffffffffffffffffffffffffffff633b9aca00911604428111612925578042034281116128f857610708106128c9575080515161272a600154610e75565b14806128a2575b815190156128625750602081015160ff815116906002549160ff8316928382149283612849575b6020015160ff169215612801575050505063ffffffff606082015116906004549163ffffffff83168082036127d357505063ffffffff608081920151169160201c168082036127a5575050565b7f1eb5c1eb000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b7f73b1bde3000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b6084945060ff90604051947fd382033a000000000000000000000000000000000000000000000000000000008652600486015260081c16602484015260448301526064820152fd5b6020810151600883901c60ff9081169116149350612758565b61261d906040519182917ff6b6676b0000000000000000000000000000000000000000000000000000000083526040600484015261260b60448401610ec6565b508051602081519101206040516128bc8161059a81610ec6565b6020815191012014612731565b7f12e74add000000000000000000000000000000000000000000000000000000005f524260045260245260445ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b7f20daedb6000000000000000000000000000000000000000000000000000000005f524260045260245260445ffd5b9067ffffffffffffffff90939293168152604060208201526080810190835191604080830152825180915260a0820190602060a08260051b8501019401915f905b8282106129d9575050505060206110d6939401519060607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc082850301910152610df8565b90919294602080612a14837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6089600196030186528951610df8565b970192019201909291612995565b60405190612a2f82611004565b5f6040838281528260208201520152565b9080601f830112156101de5781516110d6926020016111c0565b91906060838203126101de5760405190612a7382611004565b819380518352602081015167ffffffffffffffff81116101de5782612a99918301612a40565b602084015260408101519167ffffffffffffffff83116101de5760409261124a9201612a40565b9080601f830112156101de57815191612ad883611735565b92612ae6604051948561103c565b80845260208085019160051b830101918383116101de5760208101915b838310612b1257505050505090565b825167ffffffffffffffff81116101de578201906040601f1983880301126101de5760405190612b4182610f83565b602083015167ffffffffffffffff81116101de5760209084010187601f820112156101de578051612b7181611735565b91612b7f604051938461103c565b81835260208084019260051b820101918a83116101de5760208201905b838210612bdf5750505050825260408301519167ffffffffffffffff83116101de57612bd088602080969581960101612a40565b83820152815201920191612b03565b815167ffffffffffffffff81116101de57602091612c028e848094880101612a40565b815201910190612b9c565b15612c155750565b7fb0369c31000000000000000000000000000000000000000000000000000000005f52600452600160245261ffff60445260645ffd5b91909115612c57575050565b9061261d61260b926040519384937f5f1ca381000000000000000000000000000000000000000000000000000000008552604060048601526044850190610df8565b91909115612ca5575050565b604051907ffef760c700000000000000000000000000000000000000000000000000000000825280602483016020600485015252604482019260448260051b84010191815f907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603015b838310612d1e5786860387fd5b90919293947fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc8782030188528535828112156101de578301906020823592019167ffffffffffffffff81116101de5780360383136101de57602082601f19601f8480600198869897879852868601375f85828601015201160101970198019301919096939296612d11565b908151815103611b9f575f5b8251811015612e1357612dc8818461174d565b5151612dd4828461174d565b515103612e0c57612de5818461174d565b5160208151910120612df7828461174d565b516020815191012003612e0c57600101612db5565b5050505f90565b505050600190565b91612e7060209261193c60405185810190612e678161153b888591909160408060608301946fffffffffffffffffffffffffffffffff8151168452602081015160208501520151910152565b51902091611649565b0151808203612e7d575050565b7f4b2dfe98000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b929190925f5b8451811015612ee9578083612ec86001938861174d565b51604051612edf8161153b60208201948986612954565b5190205d01612eb1565b505050905056fea164736f6c634300081c000a2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d4c48d1d2b0f4f7485fc28e3db22341d96a20aa29e6efa8149da9751603abd4e06e0c24a6e293ff9b755263dbaa15ba3796b0b8d3fe17cfb4ddf8143b268eac47bd893629a699470e4ec82a5715bb4981fdaacc5d0a728bf5f55b801d8f4ef10bad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5"}} diff --git a/ibc-solidity/bun.lock b/ibc-solidity/bun.lock index 214619c2c..b47ad012c 100644 --- a/ibc-solidity/bun.lock +++ b/ibc-solidity/bun.lock @@ -12,7 +12,7 @@ "devDependencies": { "forge-std": "github:foundry-rs/forge-std#v1.15.0", "quicktype": "^23.2.6", - "solhint": "^6.2.1", + "solhint": "^6.2.4", "sp1-contracts": "github:succinctlabs/sp1-contracts#d3629729c3216eb51bd4859d027a8eb729399fa4", }, }, @@ -76,8 +76,6 @@ "ajv": ["ajv@8.18.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A=="], - "ajv-errors": ["ajv-errors@3.0.0", "", { "peerDependencies": { "ajv": "^8.0.1" } }, "sha512-V3wD15YHfHz6y0KdhYFjyy9vWtEVALT9UrxfN3zqlI6dMioHnJrqOYfyPKol3oqrnCM9uwkcdCwkJ0WUcbLMTQ=="], - "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], @@ -180,7 +178,7 @@ "graceful-fs": ["graceful-fs@4.2.10", "", {}, "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA=="], - "graphql": ["graphql@0.11.7", "", { "dependencies": { "iterall": "1.1.3" } }, "sha512-x7uDjyz8Jx+QPbpCFCMQ8lltnQa4p4vSYHx6ADe8rVYRTdsyhCJbvSty5DAsLVmU6cGakl+r8HQYolKHxk/tiw=="], + "graphql": ["graphql@16.14.2", "", {}, "sha512-Chq1s4CY7jmh8gO2qvLIJyfCDIN+EHLFW/9iShnp1z8FjBQMoodWP1kDC36VAMXXIvAjj4ARa7ntfAV2BrjsbA=="], "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], @@ -206,8 +204,6 @@ "is-url": ["is-url@1.2.4", "", {}, "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww=="], - "iterall": ["iterall@1.1.3", "", {}, "sha512-Cu/kb+4HiNSejAPhSaN1VukdNTTi/r4/e+yykqjlG/IW+1gZH5b4+Bq3whDX4tvbYugta3r8KTMUiqT3fIGxuQ=="], - "js-base64": ["js-base64@3.7.8", "", {}, "sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow=="], "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], @@ -230,7 +226,7 @@ "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="], - "lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], + "lodash": ["lodash@4.18.1", "", {}, "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q=="], "lodash.camelcase": ["lodash.camelcase@4.3.0", "", {}, "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="], @@ -288,13 +284,13 @@ "quick-lru": ["quick-lru@5.1.1", "", {}, "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA=="], - "quicktype": ["quicktype@23.2.6", "", { "dependencies": { "@glideapps/ts-necessities": "^2.2.3", "chalk": "^4.1.2", "collection-utils": "^1.0.1", "command-line-args": "^5.2.1", "command-line-usage": "^7.0.1", "cross-fetch": "^4.0.0", "graphql": "^0.11.7", "lodash": "^4.17.21", "moment": "^2.30.1", "quicktype-core": "23.2.6", "quicktype-graphql-input": "23.2.6", "quicktype-typescript-input": "23.2.6", "readable-stream": "^4.5.2", "stream-json": "1.8.0", "string-to-stream": "^3.0.1", "typescript": "~5.8.3" }, "bin": { "quicktype": "dist/index.js" } }, "sha512-rlD1jF71bOmDn6SQ/ToLuuRkMQ7maxo5oVTn5dPCl11ymqoJCFCvl7FzRfh+fkDFmWt2etl+JiIEdWImLxferA=="], + "quicktype": ["quicktype@23.3.25", "", { "dependencies": { "@glideapps/ts-necessities": "^2.2.3", "chalk": "^4.1.2", "collection-utils": "^1.0.1", "command-line-args": "^5.2.1", "command-line-usage": "^7.0.1", "cross-fetch": "^4.0.0", "graphql": "^16.11.0", "lodash": "^4.18.1", "moment": "^2.30.1", "quicktype-core": "23.3.25", "quicktype-graphql-input": "23.3.25", "quicktype-typescript-input": "23.3.25", "readable-stream": "^4.5.2", "stream-json": "1.8.0", "string-to-stream": "^3.0.1", "typescript": "~5.8.3" }, "bin": { "quicktype": "dist/index.js" } }, "sha512-I4oCxOmASNFKt3Zhsn6D1UY0pXySKqQgf2S6/bLpiYG85mqpkNT//0jZntCbyivQdqT9IVpbVy1n4NL8s42s+A=="], - "quicktype-core": ["quicktype-core@23.2.6", "", { "dependencies": { "@glideapps/ts-necessities": "2.2.3", "browser-or-node": "^3.0.0", "collection-utils": "^1.0.1", "cross-fetch": "^4.0.0", "is-url": "^1.2.4", "js-base64": "^3.7.7", "lodash": "^4.17.21", "pako": "^1.0.6", "pluralize": "^8.0.0", "readable-stream": "4.5.2", "unicode-properties": "^1.4.1", "urijs": "^1.19.1", "wordwrap": "^1.0.0", "yaml": "^2.4.1" } }, "sha512-asfeSv7BKBNVb9WiYhFRBvBZHcRutPRBwJMxW0pefluK4kkKu4lv0IvZBwFKvw2XygLcL1Rl90zxWDHYgkwCmA=="], + "quicktype-core": ["quicktype-core@23.3.25", "", { "dependencies": { "@glideapps/ts-necessities": "2.2.3", "browser-or-node": "^3.0.0", "collection-utils": "^1.0.1", "cross-fetch": "^4.0.0", "is-url": "^1.2.4", "js-base64": "^3.7.7", "lodash": "^4.18.1", "pako": "^1.0.6", "pluralize": "^8.0.0", "readable-stream": "4.5.2", "unicode-properties": "^1.4.1", "urijs": "^1.19.1", "wordwrap": "^1.0.0", "yaml": "^2.8.3" } }, "sha512-WOKJw/DemC1pO8CD0tgZ/Fn8FzWvWIeLPrbfpwfNbnPoXnehNgDRFesPYpgrNlF0Pce98aUBqqT55fsidaJGVQ=="], - "quicktype-graphql-input": ["quicktype-graphql-input@23.2.6", "", { "dependencies": { "collection-utils": "^1.0.1", "graphql": "^0.11.7", "quicktype-core": "23.2.6" } }, "sha512-jHQ8XrEaccZnWA7h/xqUQhfl+0mR5o91T6k3I4QhlnZSLdVnbycrMq4FHa9EaIFcai783JKwSUl1+koAdJq4pg=="], + "quicktype-graphql-input": ["quicktype-graphql-input@23.3.25", "", { "dependencies": { "collection-utils": "^1.0.1", "graphql": "^16.11.0", "quicktype-core": "23.3.25" } }, "sha512-bsYwcICcric9hPYfYcnfABmLEuctlaryEXma8fR/+D1LZpPTosOnfQqRgkLCRcKoP9jipP+GHWoOqMPSjXV6Mw=="], - "quicktype-typescript-input": ["quicktype-typescript-input@23.2.6", "", { "dependencies": { "@mark.probst/typescript-json-schema": "0.55.0", "quicktype-core": "23.2.6", "typescript": "4.9.5" } }, "sha512-dCNMxR+7PGs9/9Tsth9H6LOQV1G+Tv4sUGT8ZUfDRJ5Hq371qOYLma5BnLX6VxkPu8JT7mAMpQ9VFlxstX6Qaw=="], + "quicktype-typescript-input": ["quicktype-typescript-input@23.3.25", "", { "dependencies": { "@mark.probst/typescript-json-schema": "0.55.0", "quicktype-core": "23.3.25", "typescript": "4.9.5" } }, "sha512-7z2kkeG0Z8NGRiR3bo/MYSfwmhtPCHsUzxmuLZ7rrzWODfMwiCoX+C7LAo7V262HsJhiI2A0iHkYEDr0tPo5Qw=="], "rc": ["rc@1.2.8", "", { "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" }, "bin": { "rc": "./cli.js" } }, "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw=="], @@ -322,7 +318,7 @@ "slice-ansi": ["slice-ansi@4.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", "is-fullwidth-code-point": "^3.0.0" } }, "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ=="], - "solhint": ["solhint@6.2.1", "", { "dependencies": { "@solidity-parser/parser": "^0.20.2", "ajv": "^8.18.0", "ajv-errors": "^3.0.0", "ast-parents": "^0.0.1", "better-ajv-errors": "^2.0.2", "chalk": "^4.1.2", "commander": "^10.0.0", "cosmiconfig": "^8.0.0", "fast-diff": "^1.2.0", "glob": "^13.0.6", "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", "table": "^6.8.1", "text-table": "^0.2.0" }, "optionalDependencies": { "prettier": "^3.0.0" }, "bin": { "solhint": "solhint.js" } }, "sha512-+VHSa84CRjm2s+KZWYxIDnI+NokcLsZHOSpRtg5nBFmnVfh6RPmPaFd5TN922Cfrm2i85kNoQtLiapALe26b5w=="], + "solhint": ["solhint@6.2.4", "", { "dependencies": { "@solidity-parser/parser": "^0.20.2", "ajv": "^8.18.0", "ast-parents": "^0.0.1", "better-ajv-errors": "^2.0.2", "chalk": "^4.1.2", "commander": "^10.0.0", "cosmiconfig": "^8.0.0", "fast-diff": "^1.2.0", "glob": "^13.0.6", "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", "table": "^6.8.1", "text-table": "^0.2.0" }, "optionalDependencies": { "prettier": "^3.0.0" }, "bin": { "solhint": "solhint.js" } }, "sha512-2hCfsDGcCit/4Ue0Bf3HxalxEaHM/rfoSf3rMVAQQ5NWWcVPS0F+RSqQzMEPc8Ta7r5L3DeaKyzmbjD5B2fUdg=="], "sp1-contracts": ["sp1-contracts@github:succinctlabs/sp1-contracts#d362972", {}, "succinctlabs-sp1-contracts-d362972", "sha512-K8RvwZiIZxqsEgAlEE5u2CqOKBHsjekHh28u+h/EIZG1AumbC58r21JjwGK7CgQcE/Y3T6xPibtUg6ttVyaZyA=="], @@ -382,7 +378,7 @@ "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], - "yaml": ["yaml@2.8.2", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A=="], + "yaml": ["yaml@2.9.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA=="], "yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], diff --git a/ibc-solidity/contracts/ICS20Transfer.sol b/ibc-solidity/contracts/ICS20Transfer.sol index f8ebba5ac..6a05fa47c 100644 --- a/ibc-solidity/contracts/ICS20Transfer.sol +++ b/ibc-solidity/contracts/ICS20Transfer.sol @@ -255,16 +255,16 @@ contract ICS20Transfer is return _getICS26Router() .sendPacket( IICS26RouterMsgs.MsgSendPacket({ - sourceClient: msg_.sourceClient, - timeoutTimestamp: msg_.timeoutTimestamp, - payload: IICS26RouterMsgs.Payload({ - sourcePort: ICS20Lib.DEFAULT_PORT_ID, - destPort: ICS20Lib.DEFAULT_PORT_ID, - version: ICS20Lib.ICS20_VERSION, - encoding: ICS20Lib.ICS20_ENCODING, - value: abi.encode(packetData) - }) - }) + sourceClient: msg_.sourceClient, + timeoutTimestamp: msg_.timeoutTimestamp, + payload: IICS26RouterMsgs.Payload({ + sourcePort: ICS20Lib.DEFAULT_PORT_ID, + destPort: ICS20Lib.DEFAULT_PORT_ID, + version: ICS20Lib.ICS20_VERSION, + encoding: ICS20Lib.ICS20_ENCODING, + value: abi.encode(packetData) + }) + }) ); } diff --git a/ibc-solidity/contracts/ICS26Router.sol b/ibc-solidity/contracts/ICS26Router.sol index fd97f48dd..9be255768 100644 --- a/ibc-solidity/contracts/ICS26Router.sol +++ b/ibc-solidity/contracts/ICS26Router.sol @@ -174,12 +174,12 @@ contract ICS26Router is try getIBCApp(payload.destPort) .onRecvPacket( IIBCAppCallbacks.OnRecvPacketCallback({ - sourceClient: msg_.packet.sourceClient, - destinationClient: msg_.packet.destClient, - sequence: msg_.packet.sequence, - payload: payload, - relayer: _msgSender() - }) + sourceClient: msg_.packet.sourceClient, + destinationClient: msg_.packet.destClient, + sequence: msg_.packet.sequence, + payload: payload, + relayer: _msgSender() + }) ) returns ( bytes memory ack ) { @@ -238,13 +238,13 @@ contract ICS26Router is getIBCApp(payload.sourcePort) .onAcknowledgementPacket( IIBCAppCallbacks.OnAcknowledgementPacketCallback({ - sourceClient: msg_.packet.sourceClient, - destinationClient: msg_.packet.destClient, - sequence: msg_.packet.sequence, - payload: payload, - acknowledgement: msg_.acknowledgement, - relayer: _msgSender() - }) + sourceClient: msg_.packet.sourceClient, + destinationClient: msg_.packet.destClient, + sequence: msg_.packet.sequence, + payload: payload, + acknowledgement: msg_.acknowledgement, + relayer: _msgSender() + }) ); emit AckPacket(msg_.packet.sourceClient, msg_.packet.sequence, msg_.packet, msg_.acknowledgement); @@ -287,12 +287,12 @@ contract ICS26Router is getIBCApp(payload.sourcePort) .onTimeoutPacket( IIBCAppCallbacks.OnTimeoutPacketCallback({ - sourceClient: msg_.packet.sourceClient, - destinationClient: msg_.packet.destClient, - sequence: msg_.packet.sequence, - payload: payload, - relayer: _msgSender() - }) + sourceClient: msg_.packet.sourceClient, + destinationClient: msg_.packet.destClient, + sequence: msg_.packet.sequence, + payload: payload, + relayer: _msgSender() + }) ); emit TimeoutPacket(msg_.packet.sourceClient, msg_.packet.sequence, msg_.packet); diff --git a/ibc-solidity/contracts/ICS27GMP.sol b/ibc-solidity/contracts/ICS27GMP.sol index b8e4ad670..b267e3dad 100644 --- a/ibc-solidity/contracts/ICS27GMP.sol +++ b/ibc-solidity/contracts/ICS27GMP.sol @@ -114,19 +114,20 @@ contract ICS27GMP is memo: msg_.memo }); - return _getICS27GMPStorage()._ics26 + return _getICS27GMPStorage() + ._ics26 .sendPacket( IICS26RouterMsgs.MsgSendPacket({ - sourceClient: msg_.sourceClient, - timeoutTimestamp: msg_.timeoutTimestamp, - payload: IICS26RouterMsgs.Payload({ - sourcePort: ICS27Lib.DEFAULT_PORT_ID, - destPort: ICS27Lib.DEFAULT_PORT_ID, - version: ICS27Lib.ICS27_VERSION, - encoding: ICS27Lib.ICS27_ENCODING, - value: abi.encode(packetData) - }) - }) + sourceClient: msg_.sourceClient, + timeoutTimestamp: msg_.timeoutTimestamp, + payload: IICS26RouterMsgs.Payload({ + sourcePort: ICS27Lib.DEFAULT_PORT_ID, + destPort: ICS27Lib.DEFAULT_PORT_ID, + version: ICS27Lib.ICS27_VERSION, + encoding: ICS27Lib.ICS27_ENCODING, + value: abi.encode(packetData) + }) + }) ); } diff --git a/ibc-solidity/contracts/README.md b/ibc-solidity/contracts/README.md index 5aba1e2eb..21900cb09 100644 --- a/ibc-solidity/contracts/README.md +++ b/ibc-solidity/contracts/README.md @@ -22,9 +22,21 @@ This directory implements the IBC v2 protocol stack in Solidity. Most entrypoint ## Light clients (`light-clients/`) - `attestation/AttestationLightClient.sol` – m-of-n attestor-set light client using ECDSA signatures with role-gated proof submission. +- `besu/BesuIBFT2LightClient.sol` – Besu IBFT 2.0 light client for header-validator mode. Uses weak-subjectivity / trusting-period updates, verifies Besu commit seals under the existing YUI + prover sealing-header model plus EVM account/storage proofs, and proves Eureka commitments against the tracked counterparty `ICS26Router` storage. +- `besu/BesuQBFTLightClient.sol` – Besu QBFT light client for header-validator mode with the same proof model and storage verification surface as the IBFT2 wrapper, but QBFT-specific seal-digest rules within that same YUI + prover sealing-header model. - `ics02-wrapper/ICS02PrecompileWrapper.sol` – Thin adapter that exposes the `ILightClient` interface over the Cosmos EVM ICS02 precompile at a fixed address. - `sp1-ics07/SP1ICS07Tendermint.sol` – Tendermint light client verified via SP1 programs and verifier contract; supports update, (non)membership proofs, and misbehaviour handling. +### Besu light-client scope +- Supported: Besu **IBFT 2.0** and **QBFT** in **header-validator mode**. +- Verification model: weak subjectivity via **trusting period** and validator-set overlap checks. +- Commit-seal verification: follows the existing **YUI Solidity client + besu-ibc-relay-prover** sealing-header reconstruction model. +- Trusted overlap threshold: requires **strictly greater than one-third** overlap with the trusted validator set, implemented as `floor(n / 3) + 1`, which is intentionally stricter than the current upstream YUI check. +- Proof surface: Besu block headers, commit seals, Ethereum account proofs, and Ethereum storage proofs. +- Counterparty storage model: Eureka `ICS26Router` / `IBCStoreUpgradeable` commitments mapping. +- Not supported in v1: QBFT validator-contract mode, mode transitions, and misbehaviour handling. +- Current fixture status: `test/besu-bft/fixtures/` are synthetic regression fixtures; real Besu-derived golden fixtures remain a follow-up interoperability-confidence improvement. + ## Interchain Fungible Tokens (IFT) - Code reference: find the `contracts` IFT contract code [here](https://github.com/cosmos/solidity-ibc-eureka/tree/mariuszzak/ift/contracts). - IFT is an issuer-controlled ERC20 that bridges via ICS27-GMP instead of ICS20. The abstract `IFTBase` burns on send, constructs a mint call for the counterparty IFT, and tracks pending transfers keyed by (clientId, sequence). diff --git a/ibc-solidity/contracts/light-clients/besu/BesuIBFT2LightClient.sol b/ibc-solidity/contracts/light-clients/besu/BesuIBFT2LightClient.sol new file mode 100644 index 000000000..f0af3c454 --- /dev/null +++ b/ibc-solidity/contracts/light-clients/besu/BesuIBFT2LightClient.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.28; + +import { RLP } from "@openzeppelin-contracts/utils/RLP.sol"; + +import { BesuLightClientBase } from "./BesuLightClientBase.sol"; + +/// @title Besu IBFT2 Light Client +/// @notice Verifies Besu IBFT 2.0 headers and ICS26 router storage proofs. +contract BesuIBFT2LightClient is BesuLightClientBase { + /// @notice Creates a Besu IBFT2 light client from an initial trusted consensus state. + /// @param ibcRouter Counterparty ICS26 router address whose storage is proven. + /// @param initialTrustedHeight Initial trusted Besu height. + /// @param initialTrustedTimestamp Initial trusted header timestamp in seconds. + /// @param initialTrustedStorageRoot Initial trusted storage root of `ibcRouter`. + /// @param initialTrustedValidators Initial trusted validator set. + /// @param trustingPeriod Maximum age in seconds for trusted consensus states. + /// @param maxClockDrift Maximum allowed future drift in seconds for submitted headers. + /// @param roleManager Address that administers proof submission; if zero, proof submission is open. + constructor( + address ibcRouter, + uint64 initialTrustedHeight, + uint64 initialTrustedTimestamp, + bytes32 initialTrustedStorageRoot, + address[] memory initialTrustedValidators, + uint64 trustingPeriod, + uint64 maxClockDrift, + address roleManager + ) + BesuLightClientBase( + ibcRouter, + initialTrustedHeight, + initialTrustedTimestamp, + initialTrustedStorageRoot, + initialTrustedValidators, + trustingPeriod, + maxClockDrift, + roleManager + ) + { } + + /// @inheritdoc BesuLightClientBase + function _commitSealDigest(ParsedHeader memory header) internal pure override returns (bytes32) { + bytes[] memory extraItems = new bytes[](4); + extraItems[0] = _rlpItemBytes(header.extraDataItems[0]); + extraItems[1] = _rlpItemBytes(header.extraDataItems[1]); + extraItems[2] = _rlpItemBytes(header.extraDataItems[2]); + extraItems[3] = _rlpItemBytes(header.extraDataItems[3]); + + bytes memory signingExtraData = RLP.encode(extraItems); + bytes[] memory headerItems = new bytes[](header.headerItems.length); + for (uint256 i = 0; i < header.headerItems.length; ++i) { + headerItems[i] = i == 12 ? RLP.encode(signingExtraData) : _rlpItemBytes(header.headerItems[i]); + } + return keccak256(RLP.encode(headerItems)); + } +} diff --git a/ibc-solidity/contracts/light-clients/besu/BesuLightClientBase.sol b/ibc-solidity/contracts/light-clients/besu/BesuLightClientBase.sol new file mode 100644 index 000000000..1db886a1a --- /dev/null +++ b/ibc-solidity/contracts/light-clients/besu/BesuLightClientBase.sol @@ -0,0 +1,501 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.28; + +// solhint-disable gas-struct-packing, named-parameters-mapping, gas-strict-inequalities, code-complexity + +import { AccessControl } from "@openzeppelin-contracts/access/AccessControl.sol"; +import { ECDSA } from "@openzeppelin-contracts/utils/cryptography/ECDSA.sol"; + +import { ILightClient } from "../../interfaces/ILightClient.sol"; +import { ILightClientMsgs } from "../../msgs/ILightClientMsgs.sol"; +import { IICS02ClientMsgs } from "../../msgs/IICS02ClientMsgs.sol"; +import { IBesuLightClientMsgs } from "./msgs/IBesuLightClientMsgs.sol"; +import { IBesuLightClientErrors } from "./errors/IBesuLightClientErrors.sol"; +import { IBesuLightClient } from "./interfaces/IBesuLightClient.sol"; +import { RLPReader } from "./RLPReader.sol"; +import { MPTProof } from "./MPTProof.sol"; + +/// @title Besu Light Client Base +/// @notice Shared implementation for Besu BFT light clients that verify headers and EVM storage proofs. +abstract contract BesuLightClientBase is IBesuLightClient, IBesuLightClientErrors, IBesuLightClientMsgs, AccessControl { + using MPTProof for bytes; + using RLPReader for RLPReader.RLPItem; + using RLPReader for bytes; + + /// @notice Decoded fields from a submitted Besu header. + /// @param headerItems Top-level RLP header fields. + /// @param extraDataItems Decoded Besu BFT `extraData` fields. + /// @param height Header block number. + /// @param stateRoot Header state root. + /// @param timestamp Header timestamp in seconds. + /// @param validators Validator set from `extraData`. + /// @param commitSeals Commit seals from `extraData`. + struct ParsedHeader { + RLPReader.RLPItem[] headerItems; + RLPReader.RLPItem[] extraDataItems; + uint64 height; + bytes32 stateRoot; + uint64 timestamp; + address[] validators; + bytes[] commitSeals; + } + + /// @notice Role allowed to submit client updates and proof verifications. + // natlint-disable-next-line MissingInheritdoc + bytes32 public constant PROOF_SUBMITTER_ROLE = keccak256("PROOF_SUBMITTER_ROLE"); + + /// @notice Besu BFT sentinel mix hash. + bytes32 internal constant BESU_BFT_MIX_HASH = 0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365; + /// @notice Empty ommers hash required by Besu BFT headers. + bytes32 internal constant EMPTY_OMMERS_HASH = 0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347; + /// @notice ERC-7201 storage slot used by `IBCStoreUpgradeable` commitments. + bytes32 internal constant IBCSTORE_STORAGE_SLOT = + 0x1260944489272988d9df285149b5aa1b0f48f2136d6f416159f840a3e0747600; + + /// @notice Current client state. + ClientState internal clientState; + /// @notice Trusted consensus states by revision height. + mapping(uint64 revisionHeight => ConsensusState) internal consensusStates; + + /// @notice Initializes shared Besu light client state. + /// @param ibcRouter Counterparty ICS26 router address whose storage is proven. + /// @param initialTrustedHeight Initial trusted Besu height. + /// @param initialTrustedTimestamp Initial trusted header timestamp in seconds. + /// @param initialTrustedStorageRoot Initial trusted storage root of `ibcRouter`. + /// @param initialTrustedValidators Initial trusted validator set. + /// @param trustingPeriod Maximum age in seconds for trusted consensus states. + /// @param maxClockDrift Maximum allowed future drift in seconds for submitted headers. + /// @param roleManager Address that administers proof submission; if zero, proof submission is open. + constructor( + address ibcRouter, + uint64 initialTrustedHeight, + uint64 initialTrustedTimestamp, + bytes32 initialTrustedStorageRoot, + address[] memory initialTrustedValidators, + uint64 trustingPeriod, + uint64 maxClockDrift, + address roleManager + ) { + if (initialTrustedHeight == 0) { + revert InvalidHeaderHeight(); + } + if (initialTrustedTimestamp == 0) { + revert InvalidHeaderTimestamp(); + } + + _validateValidators(initialTrustedValidators); + + clientState = ClientState({ + ibcRouter: ibcRouter, + latestHeight: IICS02ClientMsgs.Height({ revisionNumber: 0, revisionHeight: initialTrustedHeight }), + trustingPeriod: trustingPeriod, + maxClockDrift: maxClockDrift + }); + + ConsensusState storage consensusState = consensusStates[initialTrustedHeight]; + consensusState.timestamp = initialTrustedTimestamp; + consensusState.storageRoot = initialTrustedStorageRoot; + consensusState.validators = initialTrustedValidators; + + if (roleManager == address(0)) { + _grantRole(PROOF_SUBMITTER_ROLE, address(0)); + } else { + _grantRole(DEFAULT_ADMIN_ROLE, roleManager); + _grantRole(PROOF_SUBMITTER_ROLE, roleManager); + } + } + + /// @inheritdoc ILightClient + function getClientState() external view returns (bytes memory) { + return abi.encode(clientState); + } + + /// @inheritdoc IBesuLightClient + function getConsensusState(uint64 revisionHeight) external view returns (bytes memory) { + ConsensusState storage consensusState = _getConsensusState(revisionHeight); + return abi.encode(consensusState.timestamp, consensusState.storageRoot, consensusState.validators); + } + + /// @inheritdoc ILightClient + function updateClient(bytes calldata updateMsg) + external + onlyProofSubmitter + returns (ILightClientMsgs.UpdateResult) + { + MsgUpdateClient memory msg_ = abi.decode(updateMsg, (MsgUpdateClient)); + _requireZeroRevision(msg_.trustedHeight.revisionNumber); + + ParsedHeader memory header = _parseHeader(msg_.headerRlp); + if (header.height == 0) { + revert InvalidHeaderHeight(); + } + if (header.timestamp == 0) { + revert InvalidHeaderTimestamp(); + } + if (block.timestamp + clientState.maxClockDrift < header.timestamp) { + revert HeaderFromFuture(block.timestamp, header.timestamp, clientState.maxClockDrift); + } + + ConsensusState storage trustedConsensusState = _getConsensusState(msg_.trustedHeight.revisionHeight); + if ( + clientState.trustingPeriod != 0 + && uint256(trustedConsensusState.timestamp) + clientState.trustingPeriod <= block.timestamp + ) { + revert ConsensusStateExpired(trustedConsensusState.timestamp, block.timestamp, clientState.trustingPeriod); + } + + address[] memory signers = _recoverSigners(_commitSealDigest(header), header.commitSeals); + _checkTrustedValidatorOverlap(signers, trustedConsensusState.validators); + _checkValidatorQuorum(signers, header.validators); + + bytes32 storageRoot = _verifyAccountProof(clientState.ibcRouter, header.stateRoot, msg_.accountProof); + + ConsensusState storage existingConsensusState = consensusStates[header.height]; + if (existingConsensusState.timestamp != 0) { + if (_isSameConsensusState(existingConsensusState, header.timestamp, storageRoot, header.validators)) { + return ILightClientMsgs.UpdateResult.NoOp; + } + revert ConflictingConsensusState(header.height); + } + + ConsensusState storage newConsensusState = consensusStates[header.height]; + newConsensusState.timestamp = header.timestamp; + newConsensusState.storageRoot = storageRoot; + newConsensusState.validators = header.validators; + + if (header.height > clientState.latestHeight.revisionHeight) { + clientState.latestHeight.revisionHeight = header.height; + } + + return ILightClientMsgs.UpdateResult.Update; + } + + /// @inheritdoc ILightClient + function verifyMembership(ILightClientMsgs.MsgVerifyMembership calldata msg_) + external + view + onlyProofSubmitter + returns (uint256) + { + _requireZeroRevision(msg_.proofHeight.revisionNumber); + if (msg_.path.length != 1) { + revert InvalidPathLength(1, msg_.path.length); + } + if (msg_.value.length != 32) { + revert InvalidValueLength(32, msg_.value.length); + } + + ConsensusState storage consensusState = _getConsensusState(msg_.proofHeight.revisionHeight); + bytes32 storageSlot = _commitmentStorageSlot(msg_.path[0]); + bytes32 expectedValue = abi.decode(msg_.value, (bytes32)); + bytes memory valueRlp = + msg_.proof.verifyRLPProof(consensusState.storageRoot, keccak256(abi.encodePacked(storageSlot))); + if (valueRlp.length == 0) { + revert InvalidCommitmentValue(expectedValue, bytes32(0)); + } + + bytes32 actualValue = bytes32(valueRlp.toRlpItem().toUint()); + if (actualValue != expectedValue) { + revert InvalidCommitmentValue(expectedValue, actualValue); + } + return consensusState.timestamp; + } + + /// @inheritdoc ILightClient + function verifyNonMembership(ILightClientMsgs.MsgVerifyNonMembership calldata msg_) + external + view + onlyProofSubmitter + returns (uint256) + { + _requireZeroRevision(msg_.proofHeight.revisionNumber); + if (msg_.path.length != 1) { + revert InvalidPathLength(1, msg_.path.length); + } + + ConsensusState storage consensusState = _getConsensusState(msg_.proofHeight.revisionHeight); + bytes32 storageSlot = _commitmentStorageSlot(msg_.path[0]); + bytes memory valueRlp = + msg_.proof.verifyRLPProof(consensusState.storageRoot, keccak256(abi.encodePacked(storageSlot))); + if (valueRlp.length != 0) { + revert ValueExists(bytes32(valueRlp.toRlpItem().toUint())); + } + return consensusState.timestamp; + } + + /// @inheritdoc ILightClient + function misbehaviour(bytes calldata) external view onlyProofSubmitter { + revert UnsupportedMisbehaviour(); + } + + /// @notice Computes the protocol-specific commit seal digest for a parsed header. + /// @param header The parsed Besu header. + /// @return The digest signed by commit seals. + function _commitSealDigest(ParsedHeader memory header) internal pure virtual returns (bytes32); + + /// @notice Parses and validates common Besu BFT header fields. + /// @param headerRlp RLP-encoded Besu block header. + /// @return header The parsed header fields used by update and proof verification. + function _parseHeader(bytes memory headerRlp) internal pure returns (ParsedHeader memory header) { + header.headerItems = headerRlp.toRlpItem().toList(); + if (header.headerItems.length < 15) { + revert InvalidHeaderFormat(header.headerItems.length); + } + + if (bytes32(header.headerItems[1].toUintStrict()) != EMPTY_OMMERS_HASH) { + revert InvalidOmmersHash(bytes32(header.headerItems[1].toUintStrict())); + } + if (header.headerItems[7].toUint() != 1) { + revert InvalidDifficulty(header.headerItems[7].toUint()); + } + if (bytes32(header.headerItems[13].toUintStrict()) != BESU_BFT_MIX_HASH) { + revert InvalidMixHash(bytes32(header.headerItems[13].toUintStrict())); + } + + bytes memory nonce = header.headerItems[14].toBytes(); + if (nonce.length != 8 || keccak256(nonce) != keccak256(hex"0000000000000000")) { + revert InvalidNonce(nonce); + } + + header.height = uint64(header.headerItems[8].toUint()); + header.stateRoot = bytes32(header.headerItems[3].toUintStrict()); + header.timestamp = uint64(header.headerItems[11].toUint()); + + bytes memory extraData = header.headerItems[12].toBytes(); + header.extraDataItems = extraData.toRlpItem().toList(); + if (header.extraDataItems.length != 5) { + revert InvalidExtraDataFormat(header.extraDataItems.length); + } + + RLPReader.RLPItem[] memory validatorItems = header.extraDataItems[1].toList(); + if (validatorItems.length == 0) { + revert EmptyValidatorSet(); + } + + header.validators = new address[](validatorItems.length); + for (uint256 i = 0; i < validatorItems.length; ++i) { + bytes memory validatorBytes = validatorItems[i].toBytes(); + if (validatorBytes.length != 20) { + revert InvalidValidatorAddressLength(validatorBytes.length); + } + + address validator = address(bytes20(validatorBytes)); + if (validator == address(0)) { + revert InvalidValidatorAddress(validator); + } + for (uint256 j = 0; j < i; ++j) { + if (header.validators[j] == validator) { + revert DuplicateValidator(validator); + } + } + header.validators[i] = validator; + } + + RLPReader.RLPItem[] memory sealItems = header.extraDataItems[4].toList(); + header.commitSeals = new bytes[](sealItems.length); + for (uint256 i = 0; i < sealItems.length; ++i) { + header.commitSeals[i] = sealItems[i].toBytes(); + } + } + + /// @notice Verifies the tracked account proof against a header state root. + /// @param account The account address being proven. + /// @param stateRoot The header state root. + /// @param accountProof RLP-encoded account proof. + /// @return The proven account storage root. + function _verifyAccountProof( + address account, + bytes32 stateRoot, + bytes memory accountProof + ) + internal + pure + returns (bytes32) + { + bytes memory accountRlp = accountProof.verifyRLPProof(stateRoot, keccak256(abi.encodePacked(account))); + RLPReader.RLPItem[] memory accountItems = accountRlp.toRlpItem().toList(); + return bytes32(accountItems[2].toUintStrict()); + } + + /// @notice Computes the storage slot used for an IBC commitment path. + /// @param rawPath Raw commitment path bytes. + /// @return The storage slot for the commitment. + function _commitmentStorageSlot(bytes memory rawPath) internal pure returns (bytes32) { + return keccak256(abi.encode(keccak256(rawPath), IBCSTORE_STORAGE_SLOT)); + } + + /// @notice Recovers unique commit seal signers for a digest. + /// @param digest The commit seal digest. + /// @param seals The commit seals to recover. + /// @return signers The recovered signer addresses. + function _recoverSigners(bytes32 digest, bytes[] memory seals) internal pure returns (address[] memory signers) { + signers = new address[](seals.length); + for (uint256 i = 0; i < seals.length; ++i) { + address signer = _recoverSigner(digest, seals[i]); + for (uint256 j = 0; j < i; ++j) { + if (signers[j] == signer) { + revert DuplicateCommitSealSigner(signer); + } + } + signers[i] = signer; + } + } + + /// @notice Recovers one commit seal signer. + /// @param digest The commit seal digest. + /// @param seal The 65-byte ECDSA commit seal. + /// @return The recovered signer address. + function _recoverSigner(bytes32 digest, bytes memory seal) internal pure returns (address) { + if (seal.length != 65) { + revert InvalidECDSASignatureLength(seal.length); + } + if (uint8(seal[64]) < 27) { + seal[64] = bytes1(uint8(seal[64]) + 27); + } + (address signer, ECDSA.RecoverError err, bytes32 errorArgument) = ECDSA.tryRecover(digest, seal); + if (err != ECDSA.RecoverError.NoError || errorArgument != bytes32(0) || signer == address(0)) { + revert InvalidCommitSeal(); + } + return signer; + } + + /// @notice Checks that signers overlap enough with the trusted validator set. + /// @param signers The recovered commit seal signers. + /// @param trustedValidators The trusted validator set. + function _checkTrustedValidatorOverlap( + address[] memory signers, + address[] storage trustedValidators + ) + internal + view + { + uint256 actual = 0; + for (uint256 i = 0; i < signers.length; ++i) { + if (_containsStorage(trustedValidators, signers[i])) { + ++actual; + } + } + + uint256 required = trustedValidators.length / 3 + 1; + if (actual < required) { + revert InsufficientTrustedValidatorOverlap(actual, required); + } + } + + /// @notice Checks that signers meet quorum for the submitted header validator set. + /// @param signers The recovered commit seal signers. + /// @param validators The validator set from the submitted header. + function _checkValidatorQuorum(address[] memory signers, address[] memory validators) internal pure { + uint256 actual = 0; + for (uint256 i = 0; i < signers.length; ++i) { + if (_containsMemory(validators, signers[i])) { + ++actual; + } + } + + // Besu requires ceil(2n / 3), equivalently n - floor(n / 3). + uint256 required = validators.length - validators.length / 3; + if (actual < required) { + revert InsufficientValidatorQuorum(actual, required); + } + } + + /// @notice Validates that a validator set is non-empty and unique. + /// @param validators The validator set to validate. + function _validateValidators(address[] memory validators) internal pure { + if (validators.length == 0) { + revert EmptyValidatorSet(); + } + for (uint256 i = 0; i < validators.length; ++i) { + if (validators[i] == address(0)) { + revert InvalidValidatorAddress(validators[i]); + } + for (uint256 j = 0; j < i; ++j) { + if (validators[j] == validators[i]) { + revert DuplicateValidator(validators[i]); + } + } + } + } + + /// @notice Compares a stored consensus state with proposed fields. + /// @param consensusState The stored consensus state. + /// @param timestamp The proposed timestamp. + /// @param storageRoot The proposed storage root. + /// @param validators The proposed validator set. + /// @return True if all fields match. + function _isSameConsensusState( + ConsensusState storage consensusState, + uint64 timestamp, + bytes32 storageRoot, + address[] memory validators + ) + internal + view + returns (bool) + { + if (consensusState.timestamp != timestamp || consensusState.storageRoot != storageRoot) { + return false; + } + return keccak256(abi.encode(consensusState.validators)) == keccak256(abi.encode(validators)); + } + + /// @notice Returns a stored consensus state or reverts if it is missing. + /// @param revisionHeight The consensus state revision height. + /// @return consensusState The stored consensus state. + function _getConsensusState(uint64 revisionHeight) internal view returns (ConsensusState storage consensusState) { + consensusState = consensusStates[revisionHeight]; + if (consensusState.timestamp == 0) { + revert ConsensusStateNotFound(revisionHeight); + } + } + + /// @notice Reverts unless the revision number is zero. + /// @param revisionNumber The revision number to validate. + function _requireZeroRevision(uint64 revisionNumber) internal pure { + if (revisionNumber != 0) { + revert InvalidRevisionNumber(revisionNumber); + } + } + + /// @notice Checks whether a storage validator set contains a signer. + /// @param validators The storage validator set. + /// @param signer The signer to find. + /// @return True if `signer` is present. + function _containsStorage(address[] storage validators, address signer) internal view returns (bool) { + for (uint256 i = 0; i < validators.length; ++i) { + if (validators[i] == signer) { + return true; + } + } + return false; + } + + /// @notice Checks whether a memory validator set contains a signer. + /// @param validators The memory validator set. + /// @param signer The signer to find. + /// @return True if `signer` is present. + function _containsMemory(address[] memory validators, address signer) internal pure returns (bool) { + for (uint256 i = 0; i < validators.length; ++i) { + if (validators[i] == signer) { + return true; + } + } + return false; + } + + /// @notice Returns the full RLP bytes for an item. + /// @param item The RLP item. + /// @return The RLP-encoded bytes. + function _rlpItemBytes(RLPReader.RLPItem memory item) internal pure returns (bytes memory) { + return item.toRlpBytes(); + } + + /// @notice Restricts access to proof submitters unless submission is open to anyone. + modifier onlyProofSubmitter() { + if (!hasRole(PROOF_SUBMITTER_ROLE, address(0))) { + _checkRole(PROOF_SUBMITTER_ROLE); + } + _; + } +} diff --git a/ibc-solidity/contracts/light-clients/besu/BesuQBFTLightClient.sol b/ibc-solidity/contracts/light-clients/besu/BesuQBFTLightClient.sol new file mode 100644 index 000000000..5cef961a6 --- /dev/null +++ b/ibc-solidity/contracts/light-clients/besu/BesuQBFTLightClient.sol @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.28; + +import { RLP } from "@openzeppelin-contracts/utils/RLP.sol"; + +import { BesuLightClientBase } from "./BesuLightClientBase.sol"; + +/// @title Besu QBFT Light Client +/// @notice Verifies Besu QBFT headers and ICS26 router storage proofs. +contract BesuQBFTLightClient is BesuLightClientBase { + /// @notice Creates a Besu QBFT light client from an initial trusted consensus state. + /// @param ibcRouter Counterparty ICS26 router address whose storage is proven. + /// @param initialTrustedHeight Initial trusted Besu height. + /// @param initialTrustedTimestamp Initial trusted header timestamp in seconds. + /// @param initialTrustedStorageRoot Initial trusted storage root of `ibcRouter`. + /// @param initialTrustedValidators Initial trusted validator set. + /// @param trustingPeriod Maximum age in seconds for trusted consensus states. + /// @param maxClockDrift Maximum allowed future drift in seconds for submitted headers. + /// @param roleManager Address that administers proof submission; if zero, proof submission is open. + constructor( + address ibcRouter, + uint64 initialTrustedHeight, + uint64 initialTrustedTimestamp, + bytes32 initialTrustedStorageRoot, + address[] memory initialTrustedValidators, + uint64 trustingPeriod, + uint64 maxClockDrift, + address roleManager + ) + BesuLightClientBase( + ibcRouter, + initialTrustedHeight, + initialTrustedTimestamp, + initialTrustedStorageRoot, + initialTrustedValidators, + trustingPeriod, + maxClockDrift, + roleManager + ) + { } + + /// @inheritdoc BesuLightClientBase + function _commitSealDigest(ParsedHeader memory header) internal pure override returns (bytes32) { + bytes[] memory extraItems = new bytes[](5); + extraItems[0] = _rlpItemBytes(header.extraDataItems[0]); + extraItems[1] = _rlpItemBytes(header.extraDataItems[1]); + extraItems[2] = _rlpItemBytes(header.extraDataItems[2]); + extraItems[3] = _rlpItemBytes(header.extraDataItems[3]); + extraItems[4] = hex"c0"; + + bytes memory signingExtraData = RLP.encode(extraItems); + bytes[] memory headerItems = new bytes[](header.headerItems.length); + for (uint256 i = 0; i < header.headerItems.length; ++i) { + headerItems[i] = i == 12 ? RLP.encode(signingExtraData) : _rlpItemBytes(header.headerItems[i]); + } + return keccak256(RLP.encode(headerItems)); + } +} diff --git a/ibc-solidity/contracts/light-clients/besu/MPTProof.sol b/ibc-solidity/contracts/light-clients/besu/MPTProof.sol new file mode 100644 index 000000000..a90e87184 --- /dev/null +++ b/ibc-solidity/contracts/light-clients/besu/MPTProof.sol @@ -0,0 +1,282 @@ +// SPDX-License-Identifier: Apache-2.0 +// This file is copied from solidity-mpt library. +// https://github.com/ibc-solidity/solidity-mpt/blob/d157b5fd0aafb0b1c23bc3a3eb5f5bc04b3fd0a3/src/MPTProof.sol +pragma solidity ^0.8.28; + +/* solhint-disable no-inline-assembly, function-max-lines, code-complexity, reason-string, gas-custom-errors, +gas-increment-by-one, gas-strict-inequalities */ + +import { RLPReader } from "./RLPReader.sol"; + +/// @title Merkle Patricia Trie Proof +/// @notice Verifies Ethereum Merkle Patricia Trie inclusion and exclusion proofs. +library MPTProof { + using RLPReader for RLPReader.RLPItem; + using RLPReader for bytes; + + /// @notice Verifies an RLP-encoded Merkle Patricia Trie proof. + /// @dev If the proof proves inclusion, the value is returned; for exclusion, an empty byte array is returned. + /// @param rlpProof is the stack of MPT nodes (starting with the root) that + /// need to be traversed during verification. It's encoded with RLP. + /// @param rootHash is the Keccak-256 hash of the root node of the MPT. + /// @param mptKey is a trie key of the node whose + /// inclusion/exclusion we are proving. + /// @return value whose inclusion is proved or an empty byte array for + /// a proof of exclusion + function verifyRLPProof( + bytes memory rlpProof, + bytes32 rootHash, + bytes32 mptKey + ) + internal + pure + returns (bytes memory value) + { + bytes memory key = new bytes(32); + assembly { + mstore(add(key, 0x20), mptKey) + } + return verify(rlpProof.toRlpItem().toList(), rootHash, decodeNibbles(key, 0)); + } + + /// @notice Verifies a decoded Merkle Patricia Trie proof. + /// @dev If the proof proves inclusion, the value is returned; for exclusion, an empty byte array is returned. + /// @param proof is the stack of MPT nodes (starting with the root) that + /// need to be traversed during verification. + /// @param rootHash is the Keccak-256 hash of the root node of the MPT. + /// @param mptKeyNibbles is the key (consisting of nibbles) of the node whose + /// inclusion/exclusion we are proving. + /// @return value whose inclusion is proved or an empty byte array for + /// a proof of exclusion + function verify( + RLPReader.RLPItem[] memory proof, + bytes32 rootHash, + bytes memory mptKeyNibbles + ) + internal + pure + returns (bytes memory value) + { + uint256 mptKeyOffset = 0; + bytes32 nodeHashHash = bytes32(0); + RLPReader.RLPItem[] memory node; + RLPReader.RLPItem memory rlpValue; + + if (proof.length == 0) { + // Root hash of empty Merkle-Patricia-Trie + require(rootHash == 0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421); + return new bytes(0); + } + + // Traverse stack of nodes starting at root. + for (uint256 i = 0; i < proof.length; i++) { + // The root node is hashed with Keccak-256 ... + if (i == 0 && rootHash != proof[i].rlpBytesKeccak256()) { + revert(); + } + // ... whereas all other nodes are hashed with the MPT + // hash function. + if (i != 0 && nodeHashHash != mptHashHash(proof[i])) { + revert(); + } + // We verified that proof[i] has the correct hash, so we + // may safely decode it. + node = proof[i].toList(); + + if (node.length == 2) { + // Extension or Leaf node + + bool isLeaf; + bytes memory nodeKey; + (isLeaf, nodeKey) = merklePatriciaCompactDecode(node[0].toBytes()); + + uint256 prefixLength = sharedPrefixLength(mptKeyOffset, mptKeyNibbles, nodeKey); + mptKeyOffset += prefixLength; + + if (prefixLength < nodeKey.length) { + // Proof claims divergent extension or leaf. (Only + // relevant for proofs of exclusion.) + // An Extension/Leaf node is divergent iff it "skips" over + // the point at which a Branch node should have been had the + // excluded key been included in the trie. + // Example: Imagine a proof of exclusion for path [1, 4], + // where the current node is a Leaf node with + // path [1, 3, 3, 7]. For [1, 4] to be included, there + // should have been a Branch node at [1] with a child + // at 3 and a child at 4. + + // Sanity check + if (i < proof.length - 1) { + // divergent node must come last in proof + revert(); + } + + return new bytes(0); + } + + if (isLeaf) { + // Sanity check + if (i < proof.length - 1) { + // leaf node must come last in proof + revert(); + } + + if (mptKeyOffset < mptKeyNibbles.length) { + return new bytes(0); + } + + rlpValue = node[1]; + return rlpValue.toBytes(); + } else { + // extension + // Sanity check + if (i == proof.length - 1) { + // shouldn't be at last level + revert(); + } + + if (!node[1].isList()) { + // rlp(child) was at least 32 bytes. node[1] contains + // Keccak256(rlp(child)). + nodeHashHash = node[1].payloadKeccak256(); + } else { + // rlp(child) was at less than 32 bytes. node[1] contains + // rlp(child). + nodeHashHash = node[1].rlpBytesKeccak256(); + } + } + } else if (node.length == 17) { + // Branch node + + if (mptKeyOffset != mptKeyNibbles.length) { + // we haven't consumed the entire path, so we need to look at a child + uint256 nibble = uint256(uint8(mptKeyNibbles[mptKeyOffset])); + mptKeyOffset += 1; + if (nibble >= 16) { + // each element of the path has to be a nibble + revert(); + } + + if (isEmptyBytesequence(node[nibble])) { + // Sanity + if (i != proof.length - 1) { + // leaf node should be at last level + revert(); + } + + return new bytes(0); + } else if (!node[nibble].isList()) { + nodeHashHash = node[nibble].payloadKeccak256(); + } else { + nodeHashHash = node[nibble].rlpBytesKeccak256(); + } + } else { + // we have consumed the entire mptKey, so we need to look at what's contained in this node. + + // Sanity + if (i != proof.length - 1) { + // should be at last level + revert(); + } + + return node[16].toBytes(); + } + } else { + revert("invalid node length"); + } + } + // unreachable here + revert(); + } + + /// @notice Checks whether an RLP item is the empty byte sequence. + /// @param item The RLP item to check. + /// @return True if the item encodes an empty byte sequence. + function isEmptyBytesequence(RLPReader.RLPItem memory item) internal pure returns (bool) { + if (item.len != 1) { + return false; + } + uint8 b; + uint256 memPtr = item.memPtr; + assembly { + b := byte(0, mload(memPtr)) + } + return b == 0x80; /* empty byte string */ + } + + /// @notice Expands bytes into nibbles starting at an offset. + /// @param bz The bytes to expand. + /// @param offset The nibble offset. + /// @return nibbles The expanded nibbles. + function decodeNibbles(bytes memory bz, uint256 offset) internal pure returns (bytes memory nibbles) { + uint256 length = bz.length * 2; + require(bz.length > 0 && offset <= length); + + nibbles = new bytes(length - offset); + uint256 i = offset; + if (offset & 1 == 1) { + nibbles[0] = bytes1((uint8(bz[offset / 2]) >> 0) & 0xF); + i++; + } + unchecked { + for (; i < length - 1; i += 2) { + nibbles[i - offset] = bytes1((uint8(bz[i / 2]) >> 4) & 0xF); + nibbles[i - offset + 1] = bytes1((uint8(bz[i / 2]) >> 0) & 0xF); + } + } + } + + /// @notice Decodes compact Merkle Patricia Trie path encoding. + /// @param bz The compact encoded path bytes. + /// @return isLeaf True if the compact path marks a leaf node. + /// @return nibbles The decoded path nibbles. + function merklePatriciaCompactDecode(bytes memory bz) internal pure returns (bool isLeaf, bytes memory nibbles) { + require(bz.length > 0); + uint256 firstNibble = uint8(bz[0]) >> 4 & 0xF; + uint256 offset = 0; + if (firstNibble == 0) { + offset = 2; + isLeaf = false; + } else if (firstNibble == 1) { + offset = 1; + isLeaf = false; + } else if (firstNibble == 2) { + offset = 2; + isLeaf = true; + } else if (firstNibble == 3) { + offset = 1; + isLeaf = true; + } else { + // Not supposed to happen! + revert(); + } + return (isLeaf, decodeNibbles(bz, offset)); + } + + /// @notice Computes the shared prefix length between two nibble arrays. + /// @param xsOffset Offset into `xs` where comparison starts. + /// @param xs The first nibble array. + /// @param ys The second nibble array. + /// @return The number of matching nibbles. + function sharedPrefixLength(uint256 xsOffset, bytes memory xs, bytes memory ys) internal pure returns (uint256) { + uint256 i = 0; + for (; i + xsOffset < xs.length && i < ys.length; i++) { + if (xs[i + xsOffset] != ys[i]) { + return i; + } + } + return i; + } + + /// @notice Computes the keccak256 hash of the Merkle Patricia Trie hash of an item. + /// @dev MPT hashes are variable length: short inputs are inlined, long inputs are keccak256-hashed. + /// @param input The byte sequence to be hashed. + /// @return Keccak-256(MPT-hash(input)) + function mptHashHash(RLPReader.RLPItem memory input) internal pure returns (bytes32) { + if (input.len < 32) { + return input.rlpBytesKeccak256(); + } else { + return keccak256(abi.encodePacked(input.rlpBytesKeccak256())); + } + } +} diff --git a/ibc-solidity/contracts/light-clients/besu/README.md b/ibc-solidity/contracts/light-clients/besu/README.md new file mode 100644 index 000000000..88099b401 --- /dev/null +++ b/ibc-solidity/contracts/light-clients/besu/README.md @@ -0,0 +1,134 @@ +# Besu IBFT 2.0 / QBFT Light Clients + +This module contains two Solidity light clients for Besu BFT chains: + +- `BesuIBFT2LightClient.sol` +- `BesuQBFTLightClient.sol` + +Both wrappers share the same storage model and proof surface through `BesuLightClientBase.sol`. They differ only in how the commit-seal signing digest is reconstructed from the raw Besu header. + +## Verification model notes + +- Commit-seal verification follows the existing **YUI Solidity client + besu-ibc-relay-prover** model: reconstruct the sealing header by rewriting `extraData` into the protocol-specific signing form, then recover commit-seal signers from the `keccak256(RLP(header))` digest. +- This module does **not** claim to independently rederive a distinct Besu network-level consensus-message payload beyond that established YUI/prover model. +- Trusted overlap is intentionally **strictly greater than one-third** of the trusted validator set, implemented as `floor(n / 3) + 1`. This is intentionally stricter than the current upstream YUI overlap check. + +## Supported scope + +- Besu **IBFT 2.0** +- Besu **QBFT** +- **Header-validator mode only** +- Weak-subjectivity / **trusting-period** verification +- Ethereum **account proofs** and **storage proofs** +- Eureka commitment verification against the counterparty `ICS26Router` proxy account + +## Out of scope in v1 + +- QBFT validator-contract mode +- Mode transitions +- Misbehaviour evidence handling +- Frozen-client machinery + +## Constructor + +Both wrappers take the same constructor arguments: + +```solidity +constructor( + address ibcRouter, + uint64 initialTrustedHeight, + uint64 initialTrustedTimestamp, + bytes32 initialTrustedStorageRoot, + address[] memory initialTrustedValidators, + uint64 trustingPeriod, + uint64 maxClockDrift, + address roleManager +) +``` + +- `ibcRouter`: counterparty `ICS26Router` proxy address whose account/storage proofs are tracked. +- `initialTrustedHeight`: trusted Besu block number. Revision number is always `0`. +- `initialTrustedTimestamp`: trusted header timestamp in seconds. +- `initialTrustedStorageRoot`: storage root of the tracked `ICS26Router` account at `initialTrustedHeight`. +- `initialTrustedValidators`: validator set trusted at `initialTrustedHeight`. +- `trustingPeriod`: weak-subjectivity window in seconds. `0` means no expiry. +- `maxClockDrift`: allowed future drift for submitted headers in seconds. +- `roleManager`: if non-zero, receives admin and `PROOF_SUBMITTER_ROLE`; if zero, proof submission is open to anyone through the zero-address sentinel. + +## `updateClient(bytes)` ABI + +`updateClient` expects `abi.encode(IBesuLightClientMsgs.MsgUpdateClient)`: + +```solidity +struct MsgUpdateClient { + bytes headerRlp; + IICS02ClientMsgs.Height trustedHeight; + bytes accountProof; +} +``` + +- `headerRlp`: full raw Besu block header RLP, including `extraData` and commit seals. +- `trustedHeight`: must use `revisionNumber == 0`. +- `accountProof`: raw RLP-encoded Ethereum account proof for the tracked `ICS26Router` account against the submitted header's `stateRoot`. + +On update, the contract: + +1. parses and validates the Besu header, +2. reconstructs the protocol-specific commit-seal digest following the YUI + prover sealing-header model, +3. checks trusted-validator overlap and new-validator quorum, +4. verifies the tracked router account proof, +5. stores the router account `storageRoot` plus the new validator set. + +## Membership / non-membership proofs + +`verifyMembership` and `verifyNonMembership` expect the standard `ILightClientMsgs` payloads used by Eureka. + +For Besu / EVM counterparties, the expected merkle prefix is: + +```solidity +[bytes("")] +``` + +That means `msg_.path[0]` is the raw Eureka commitment path bytes. + +### Storage slot derivation + +The counterparty `ICS26Router` stores commitments in `IBCStoreUpgradeable` as: + +```solidity +mapping(bytes32 hashedPath => bytes32 commitment) commitments; +``` + +The proof key is derived as: + +```solidity +bytes32 hashedPath = keccak256(rawPath); +bytes32 storageSlot = keccak256(abi.encode(hashedPath, IBCSTORE_STORAGE_SLOT)); +``` + +where `IBCSTORE_STORAGE_SLOT` is the ERC-7201 namespace constant used by `IBCStoreUpgradeable`. + +### Membership + +- `msg_.proof` must be the raw RLP-encoded Ethereum storage proof for `storageSlot`. +- `msg_.value` must be exactly `abi.encodePacked(bytes32Commitment)`. +- The return value is the trusted consensus timestamp in seconds for `msg_.proofHeight`. + +### Non-membership + +- `msg_.proof` must be the raw RLP-encoded Ethereum storage proof for `storageSlot`. +- The proof must show that the slot is absent. +- The return value is the trusted consensus timestamp in seconds for `msg_.proofHeight`. + +## Test fixtures + +The Foundry fixtures under `test/besu-bft/fixtures/` can be regenerated from the focused Besu↔Besu e2e flow: + +```sh +GENERATE_BESU_LIGHT_CLIENT_FIXTURES=true \ +just test-e2e TestWithBesuToBesuTestSuite/Test_ICS20TransferERC20FromChainAToChainB +``` + +This writes `test/besu-bft/fixtures/qbft.json` using live Besu QBFT headers, account proofs, and storage proofs captured during the e2e transfer flow. The negative cases in that fixture are still derived by deterministic off-chain header mutation so the contract tests can keep explicit overlap / quorum / conflict coverage. + +`ibft2.json` remains synthetic until an IBFT2-focused e2e fixture path is added. diff --git a/ibc-solidity/contracts/light-clients/besu/RLPReader.sol b/ibc-solidity/contracts/light-clients/besu/RLPReader.sol new file mode 100644 index 000000000..173b50a96 --- /dev/null +++ b/ibc-solidity/contracts/light-clients/besu/RLPReader.sol @@ -0,0 +1,300 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * @author Hamdi Allam hamdi.allam97@gmail.com + * Please reach out with any questions or concerns + */ +// This file is adapted from the solidity-rlp library. +// https://github.com/hamdiallam/Solidity-RLP/blob/0212f8e754471da67fc5387df7855f47f944f925/contracts/RLPReader.sol +pragma solidity ^0.8.28; + +/* solhint-disable state-visibility, no-inline-assembly, reason-string, gas-custom-errors, gas-increment-by-one, +gas-strict-inequalities */ + +/// @title RLP Reader +/// @notice Library for reading Recursive Length Prefix encoded values. +library RLPReader { + /// @notice First byte for short RLP strings. + uint8 constant STRING_SHORT_START = 0x80; + /// @notice First byte for long RLP strings. + uint8 constant STRING_LONG_START = 0xb8; + /// @notice First byte for short RLP lists. + uint8 constant LIST_SHORT_START = 0xc0; + /// @notice First byte for long RLP lists. + uint8 constant LIST_LONG_START = 0xf8; + /// @notice EVM word size in bytes. + uint8 constant WORD_SIZE = 32; + + /// @notice RLP item memory view. + /// @param len Length of the encoded item. + /// @param memPtr Memory pointer to the encoded item. + struct RLPItem { + uint256 len; + uint256 memPtr; + } + + /// @notice Wraps RLP-encoded bytes as an RLP item. + /// @param item RLP-encoded bytes. + /// @return The RLP item memory view. + function toRlpItem(bytes memory item) internal pure returns (RLPItem memory) { + uint256 memPtr; + assembly { + memPtr := add(item, 0x20) + } + + return RLPItem(item.length, memPtr); + } + + /// @notice Returns the payload memory location for an RLP item. + /// @param item The RLP item. + /// @return The payload memory pointer. + /// @return The payload length. + function payloadLocation(RLPItem memory item) internal pure returns (uint256, uint256) { + uint256 offset = _payloadOffset(item.memPtr); + uint256 memPtr = item.memPtr + offset; + uint256 len = item.len - offset; // data length + return (memPtr, len); + } + + /// @notice Decodes an RLP list into item views. + /// @param item The RLP list item. + /// @return The list item views. + function toList(RLPItem memory item) internal pure returns (RLPItem[] memory) { + require(isList(item)); + + uint256 items = numItems(item); + RLPItem[] memory result = new RLPItem[](items); + + uint256 memPtr = item.memPtr + _payloadOffset(item.memPtr); + uint256 dataLen; + for (uint256 i = 0; i < items; i++) { + dataLen = _itemLength(memPtr); + result[i] = RLPItem(dataLen, memPtr); + memPtr = memPtr + dataLen; + } + + return result; + } + + /// @notice Checks whether an RLP item is a list. + /// @param item The RLP item. + /// @return True if the encoded payload is a list. + function isList(RLPItem memory item) internal pure returns (bool) { + if (item.len == 0) return false; + + uint8 byte0; + uint256 memPtr = item.memPtr; + assembly { + byte0 := byte(0, mload(memPtr)) + } + + if (byte0 < LIST_SHORT_START) return false; + return true; + } + + /// @notice Computes the keccak256 hash of the full RLP encoding without copying. + /// @param item The RLP item. + /// @return The keccak256 hash of the encoded item. + function rlpBytesKeccak256(RLPItem memory item) internal pure returns (bytes32) { + uint256 ptr = item.memPtr; + uint256 len = item.len; + bytes32 result; + assembly { + result := keccak256(ptr, len) + } + return result; + } + + /// @notice Computes the keccak256 hash of an RLP payload without copying. + /// @param item The RLP item. + /// @return The keccak256 hash of the item payload. + function payloadKeccak256(RLPItem memory item) internal pure returns (bytes32) { + (uint256 memPtr, uint256 len) = payloadLocation(item); + bytes32 result; + assembly { + result := keccak256(memPtr, len) + } + return result; + } + + /* + * RLPItem conversions into data types. + */ + + /// @notice Copies the full RLP encoding into a bytes array. + /// @param item The RLP item. + /// @return The RLP-encoded bytes. + function toRlpBytes(RLPItem memory item) internal pure returns (bytes memory) { + bytes memory result = new bytes(item.len); + if (result.length == 0) return result; + + uint256 ptr; + assembly { + ptr := add(0x20, result) + } + + copy(item.memPtr, ptr, item.len); + return result; + } + + /// @notice Converts an RLP item to an unsigned integer. + /// @param item The RLP item. + /// @return The decoded unsigned integer. + function toUint(RLPItem memory item) internal pure returns (uint256) { + require(item.len > 0 && item.len <= 33); + + (uint256 memPtr, uint256 len) = payloadLocation(item); + + uint256 result; + assembly { + result := mload(memPtr) + + // shift to the correct location if neccesary + if lt(len, 32) { result := div(result, exp(256, sub(32, len))) } + } + + return result; + } + + /// @notice Converts an RLP item to an unsigned integer and requires a 32-byte payload. + /// @param item The RLP item. + /// @return The decoded unsigned integer. + function toUintStrict(RLPItem memory item) internal pure returns (uint256) { + // one byte prefix + require(item.len == 33); + + uint256 result; + uint256 memPtr = item.memPtr + 1; + assembly { + result := mload(memPtr) + } + + return result; + } + + /// @notice Copies an RLP item payload into a bytes array. + /// @param item The RLP item. + /// @return The decoded payload bytes. + function toBytes(RLPItem memory item) internal pure returns (bytes memory) { + require(item.len > 0); + + (uint256 memPtr, uint256 len) = payloadLocation(item); + bytes memory result = new bytes(len); + + uint256 destPtr; + assembly { + destPtr := add(0x20, result) + } + + copy(memPtr, destPtr, len); + return result; + } + + /* + * Private Helpers + */ + + /// @notice Counts the payload items inside an encoded list. + /// @param item The RLP list item. + /// @return The number of items in the list. + function numItems(RLPItem memory item) private pure returns (uint256) { + if (item.len == 0) return 0; + + uint256 count = 0; + uint256 currPtr = item.memPtr + _payloadOffset(item.memPtr); + uint256 endPtr = item.memPtr + item.len; + while (currPtr < endPtr) { + currPtr = currPtr + _itemLength(currPtr); // skip over an item + count++; + } + + return count; + } + + /// @notice Computes the full encoded byte length of an RLP item at a memory pointer. + /// @param memPtr Memory pointer to the item. + /// @return The encoded item length. + function _itemLength(uint256 memPtr) private pure returns (uint256) { + uint256 itemLen; + uint256 byte0; + assembly { + byte0 := byte(0, mload(memPtr)) + } + + if (byte0 < STRING_SHORT_START) { + itemLen = 1; + } else if (byte0 < STRING_LONG_START) { + itemLen = byte0 - STRING_SHORT_START + 1; + } else if (byte0 < LIST_SHORT_START) { + assembly { + let byteLen := sub(byte0, 0xb7) // # of bytes the actual length is + memPtr := add(memPtr, 1) // skip over the first byte + + /* 32 byte word size */ + let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to get the len + itemLen := add(dataLen, add(byteLen, 1)) + } + } else if (byte0 < LIST_LONG_START) { + itemLen = byte0 - LIST_SHORT_START + 1; + } else { + assembly { + let byteLen := sub(byte0, 0xf7) + memPtr := add(memPtr, 1) + + let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to the correct length + itemLen := add(dataLen, add(byteLen, 1)) + } + } + + return itemLen; + } + + /// @notice Computes the offset from an RLP item prefix to its payload. + /// @param memPtr Memory pointer to the item. + /// @return The payload offset in bytes. + function _payloadOffset(uint256 memPtr) private pure returns (uint256) { + uint256 byte0; + assembly { + byte0 := byte(0, mload(memPtr)) + } + + if (byte0 < STRING_SHORT_START) { + return 0; + } else if (byte0 < STRING_LONG_START || (byte0 >= LIST_SHORT_START && byte0 < LIST_LONG_START)) { + return 1; + } else if (byte0 < LIST_SHORT_START) { + // being explicit + return byte0 - (STRING_LONG_START - 1) + 1; + } else { + return byte0 - (LIST_LONG_START - 1) + 1; + } + } + + /// @notice Copies memory from one pointer to another. + /// @param src Pointer to the source memory. + /// @param dest Pointer to the destination memory. + /// @param len Number of bytes to copy. + function copy(uint256 src, uint256 dest, uint256 len) private pure { + if (len == 0) return; + + // copy as many word sizes as possible + for (; len >= WORD_SIZE; len -= WORD_SIZE) { + assembly { + mstore(dest, mload(src)) + } + + src += WORD_SIZE; + dest += WORD_SIZE; + } + + if (len > 0) { + // left over bytes. Mask is used to remove unwanted bytes from the word + uint256 mask = 256 ** (WORD_SIZE - len) - 1; + assembly { + let srcpart := and(mload(src), not(mask)) // zero out src + let destpart := and(mload(dest), mask) // retrieve the bytes + mstore(dest, or(destpart, srcpart)) + } + } + } +} diff --git a/ibc-solidity/contracts/light-clients/besu/errors/IBesuLightClientErrors.sol b/ibc-solidity/contracts/light-clients/besu/errors/IBesuLightClientErrors.sol new file mode 100644 index 000000000..ff87b4b26 --- /dev/null +++ b/ibc-solidity/contracts/light-clients/besu/errors/IBesuLightClientErrors.sol @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.28; + +/// @title Besu Light Client Errors +/// @notice Error interface for Besu BFT light clients. +interface IBesuLightClientErrors { + /// @notice The revision number must be zero for Besu light client heights. + /// @param providedRevisionNumber The non-zero revision number. + error InvalidRevisionNumber(uint64 providedRevisionNumber); + /// @notice The submitted header has an invalid RLP item count. + /// @param itemsLength The decoded header item count. + error InvalidHeaderFormat(uint256 itemsLength); + /// @notice The submitted `extraData` field has an invalid RLP item count. + /// @param itemsLength The decoded `extraData` item count. + error InvalidExtraDataFormat(uint256 itemsLength); + /// @notice The submitted header height is zero. + error InvalidHeaderHeight(); + /// @notice The submitted header timestamp is zero. + error InvalidHeaderTimestamp(); + /// @notice The submitted header timestamp is too far in the future. + /// @param currentTimestamp The current block timestamp. + /// @param headerTimestamp The submitted header timestamp. + /// @param maxClockDrift The configured maximum clock drift. + error HeaderFromFuture(uint256 currentTimestamp, uint256 headerTimestamp, uint256 maxClockDrift); + /// @notice No consensus state exists for the requested height. + /// @param revisionHeight The requested revision height. + error ConsensusStateNotFound(uint64 revisionHeight); + /// @notice The trusted consensus state is outside the trusting period. + /// @param trustedTimestamp Timestamp of the trusted consensus state. + /// @param currentTimestamp The current block timestamp. + /// @param trustingPeriod The configured trusting period. + error ConsensusStateExpired(uint64 trustedTimestamp, uint256 currentTimestamp, uint64 trustingPeriod); + /// @notice The Besu BFT mix hash is invalid. + /// @param actualMixHash The mix hash found in the header. + error InvalidMixHash(bytes32 actualMixHash); + /// @notice The Besu BFT difficulty is invalid. + /// @param actualDifficulty The difficulty found in the header. + error InvalidDifficulty(uint256 actualDifficulty); + /// @notice The Besu BFT nonce is invalid. + /// @param actualNonce The nonce found in the header. + error InvalidNonce(bytes actualNonce); + /// @notice The ommers hash is invalid. + /// @param actualOmmersHash The ommers hash found in the header. + error InvalidOmmersHash(bytes32 actualOmmersHash); + /// @notice The validator set is empty. + error EmptyValidatorSet(); + /// @notice A validator address has an invalid byte length. + /// @param length The decoded validator address length. + error InvalidValidatorAddressLength(uint256 length); + /// @notice A validator address is invalid. + /// @param validator The invalid validator address. + error InvalidValidatorAddress(address validator); + /// @notice A validator appears more than once. + /// @param validator The duplicate validator address. + error DuplicateValidator(address validator); + /// @notice A commit seal signer appears more than once. + /// @param signer The duplicate signer address. + error DuplicateCommitSealSigner(address signer); + /// @notice An ECDSA signature has an invalid length. + /// @param length The invalid signature length. + error InvalidECDSASignatureLength(uint256 length); + /// @notice A commit seal did not recover a valid signer. + error InvalidCommitSeal(); + /// @notice The submitted signers do not overlap enough with the trusted validator set. + /// @param actual The number of trusted validators that signed. + /// @param required The minimum required trusted signer count. + error InsufficientTrustedValidatorOverlap(uint256 actual, uint256 required); + /// @notice The submitted signers do not meet quorum for the new validator set. + /// @param actual The number of new validators that signed. + /// @param required The minimum required signer count. + error InsufficientValidatorQuorum(uint256 actual, uint256 required); + /// @notice A proof path has an invalid length. + /// @param expectedLength The expected path length. + /// @param actualLength The actual path length. + error InvalidPathLength(uint256 expectedLength, uint256 actualLength); + /// @notice A membership value has an invalid length. + /// @param expectedLength The expected value length. + /// @param actualLength The actual value length. + error InvalidValueLength(uint256 expectedLength, uint256 actualLength); + /// @notice A proven commitment value does not match the expected value. + /// @param expectedValue The expected commitment value. + /// @param actualValue The proven commitment value. + error InvalidCommitmentValue(bytes32 expectedValue, bytes32 actualValue); + /// @notice A non-membership proof found an existing value. + /// @param actualValue The value found at the proven storage slot. + error ValueExists(bytes32 actualValue); + /// @notice A different consensus state already exists at the submitted height. + /// @param revisionHeight The conflicting revision height. + error ConflictingConsensusState(uint64 revisionHeight); + /// @notice Misbehaviour handling is not supported by this client. + error UnsupportedMisbehaviour(); +} diff --git a/ibc-solidity/contracts/light-clients/besu/interfaces/IBesuLightClient.sol b/ibc-solidity/contracts/light-clients/besu/interfaces/IBesuLightClient.sol new file mode 100644 index 000000000..8374a32b6 --- /dev/null +++ b/ibc-solidity/contracts/light-clients/besu/interfaces/IBesuLightClient.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.28; + +import { ILightClient } from "../../../interfaces/ILightClient.sol"; + +/// @title IBesuLightClient +/// @notice Interface for Besu BFT light clients. +interface IBesuLightClient is ILightClient { + /// @notice Returns the trusted consensus state at a revision height. + /// @param revisionHeight The revision height to query. + /// @return The ABI-encoded consensus state. + function getConsensusState(uint64 revisionHeight) external view returns (bytes memory); +} diff --git a/ibc-solidity/contracts/light-clients/besu/msgs/IBesuLightClientMsgs.sol b/ibc-solidity/contracts/light-clients/besu/msgs/IBesuLightClientMsgs.sol new file mode 100644 index 000000000..5617e9f65 --- /dev/null +++ b/ibc-solidity/contracts/light-clients/besu/msgs/IBesuLightClientMsgs.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.28; + +import { IICS02ClientMsgs } from "../../../msgs/IICS02ClientMsgs.sol"; + +/// @title Besu Light Client Messages +/// @notice Defines shared message and state types for Besu BFT light clients. +interface IBesuLightClientMsgs { + /// @notice Client state for a Besu BFT light client. + /// @param ibcRouter Counterparty ICS26 router address whose storage is proven. + /// @param latestHeight Latest trusted Besu height. + /// @param trustingPeriod Maximum age in seconds for a trusted consensus state. + /// @param maxClockDrift Maximum allowed future drift in seconds for submitted headers. + struct ClientState { + address ibcRouter; + IICS02ClientMsgs.Height latestHeight; + uint64 trustingPeriod; + uint64 maxClockDrift; + } + + /// @notice Trusted consensus state for a Besu height. + /// @param timestamp Header timestamp in seconds. + /// @param storageRoot Storage root of the tracked ICS26 router account. + /// @param validators Validator set committed in the header. + struct ConsensusState { + uint64 timestamp; + bytes32 storageRoot; + address[] validators; + } + + /// @notice Update message containing a Besu header and account proof. + /// @param headerRlp RLP-encoded Besu block header. + /// @param trustedHeight Previously trusted height used for weak-subjectivity checks. + /// @param accountProof Ethereum account proof for the tracked ICS26 router. + struct MsgUpdateClient { + bytes headerRlp; + IICS02ClientMsgs.Height trustedHeight; + bytes accountProof; + } +} diff --git a/ibc-solidity/foundry.toml b/ibc-solidity/foundry.toml index b771f8d1b..e8cb233b1 100644 --- a/ibc-solidity/foundry.toml +++ b/ibc-solidity/foundry.toml @@ -7,6 +7,7 @@ evm_version = "cancun" fuzz = { runs = 100_000 } gas_reports = ["*"] + isolate = false optimizer = true via_ir = true # This is needed because of the `sp1-ics07-tendermint` contract optimizer_runs = 10_000 diff --git a/ibc-solidity/nix/node-modules.nix b/ibc-solidity/nix/node-modules.nix index df96ebaab..3b8f35269 100644 --- a/ibc-solidity/nix/node-modules.nix +++ b/ibc-solidity/nix/node-modules.nix @@ -38,5 +38,5 @@ in outputHashMode = "recursive"; outputHashAlgo = "sha256"; - outputHash = "sha256-yVgjaDQkaau/fFwP1OBlOBNJXpLFQ+dvVcbTeR0gvEY="; + outputHash = "sha256-FRAFooYq0VvwQoSMNU84MruSCoyU2bTKhm+BxfVnjSc="; } diff --git a/ibc-solidity/package.json b/ibc-solidity/package.json index 160c5be69..ae89daeda 100644 --- a/ibc-solidity/package.json +++ b/ibc-solidity/package.json @@ -11,8 +11,8 @@ "devDependencies": { "sp1-contracts": "github:succinctlabs/sp1-contracts#d3629729c3216eb51bd4859d027a8eb729399fa4", "forge-std": "github:foundry-rs/forge-std#v1.15.0", - "solhint": "^6.2.1", - "quicktype": "^23.2.6" + "solhint": "^6.2.4", + "quicktype": "^23.3.25" }, "keywords": [ "blockchain", diff --git a/ibc-solidity/solidity.just b/ibc-solidity/solidity.just index 112c9f70f..ad04cdf7d 100644 --- a/ibc-solidity/solidity.just +++ b/ibc-solidity/solidity.just @@ -33,7 +33,7 @@ test-foundry testname=".\\*": test-benchmark testname=".\\*": forge test -vvv --show-progress --gas-report --match-path test/solidity-ibc/BenchmarkTest.t.sol --match-test {{testname}} -# Generate ABI/bin artifacts and Go abigen bindings +# Generate all tracked contract artifacts and Go abigen bindings [group('generate')] generate-abi: build-contracts mkdir -p tmp/abigen @@ -55,6 +55,8 @@ generate-abi: build-contracts jq -r '.bytecode.object' out/RelayerHelper.sol/RelayerHelper.json > tmp/abigen/RelayerHelper.bin jq '.abi' out/AttestationLightClient.sol/AttestationLightClient.json > abi/AttestationLightClient.json jq -r '.bytecode.object' out/AttestationLightClient.sol/AttestationLightClient.json > tmp/abigen/AttestationLightClient.bin + jq '.abi' out/BesuIBFT2LightClient.sol/BesuIBFT2LightClient.json > abi/BesuIBFT2LightClient.json + jq '.abi' out/BesuQBFTLightClient.sol/BesuQBFTLightClient.json > abi/BesuQBFTLightClient.json jq '.abi' out/IFTOwnable.sol/IFTOwnable.json > abi/IFTOwnable.json jq -r '.bytecode.object' out/IFTOwnable.sol/IFTOwnable.json > tmp/abigen/IFTOwnable.bin jq '.abi' out/ERC1967Proxy.sol/ERC1967Proxy.json > abi/ERC1967Proxy.json @@ -73,14 +75,14 @@ generate-abi: build-contracts abigen --abi abi/AttestationLightClient.json --bin tmp/abigen/AttestationLightClient.bin --pkg attestation --type Contract --out ../packages/go-abigen/attestation/contract.go abigen --abi abi/ERC1967Proxy.json --bin tmp/abigen/ERC1967Proxy.bin --pkg erc1967proxy --type Contract --out ../packages/go-abigen/erc1967proxy/contract.go abigen --abi abi/EVMIFTSendCallConstructor.json --bin tmp/abigen/EVMIFTSendCallConstructor.bin --pkg evmiftsendcall --type Contract --out ../packages/go-abigen/evmiftsendcall/contract.go + rm -rf abi/bytecode + mkdir -p abi/bytecode + jq -c '{abi, bytecode: {object: .bytecode.object}}' out/SP1ICS07Tendermint.sol/SP1ICS07Tendermint.json > abi/bytecode/SP1ICS07Tendermint.json + jq -c '{abi, bytecode: {object: .bytecode.object}}' out/AttestationLightClient.sol/AttestationLightClient.json > abi/bytecode/AttestationLightClient.json + jq -c '{abi, bytecode: {object: .bytecode.object}}' out/BesuIBFT2LightClient.sol/BesuIBFT2LightClient.json > abi/bytecode/BesuIBFT2LightClient.json + jq -c '{abi, bytecode: {object: .bytecode.object}}' out/BesuQBFTLightClient.sol/BesuQBFTLightClient.json > abi/bytecode/BesuQBFTLightClient.json rm -rf tmp/abigen -# Generate the ABI files with bytecode for the required contracts -[group('generate')] -generate-abi-bytecode: build-contracts - cp out/SP1ICS07Tendermint.sol/SP1ICS07Tendermint.json abi/bytecode - cp out/AttestationLightClient.sol/AttestationLightClient.json abi/bytecode - # Clean up the foundry cache and out directories [group('clean')] clean-foundry: diff --git a/ibc-solidity/test/besu-bft/BesuIBFT2LightClient.t.sol b/ibc-solidity/test/besu-bft/BesuIBFT2LightClient.t.sol new file mode 100644 index 000000000..6376c62c9 --- /dev/null +++ b/ibc-solidity/test/besu-bft/BesuIBFT2LightClient.t.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.28; + +import { IBesuLightClient } from "../../contracts/light-clients/besu/interfaces/IBesuLightClient.sol"; +import { BesuLightClientFixtureTestBase } from "./BesuLightClientFixtureTestBase.sol"; + +contract BesuIBFT2LightClientTest is BesuLightClientFixtureTestBase { + function _fixtureFile() internal pure override returns (string memory) { + return "ibft2.json"; + } + + function _deployPrimaryClient() internal override returns (IBesuLightClient) { + return _deployIBFT2(); + } + + function _deployWrongWrapper() internal override returns (IBesuLightClient) { + return _deployQBFT(); + } +} diff --git a/ibc-solidity/test/besu-bft/BesuLightClientFixtureTestBase.sol b/ibc-solidity/test/besu-bft/BesuLightClientFixtureTestBase.sol new file mode 100644 index 000000000..4d82e0615 --- /dev/null +++ b/ibc-solidity/test/besu-bft/BesuLightClientFixtureTestBase.sol @@ -0,0 +1,456 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.28; + +// solhint-disable gas-struct-packing,function-max-lines,gas-small-strings + +import { Test } from "forge-std/Test.sol"; +import { stdJson } from "forge-std/StdJson.sol"; + +import { ILightClientMsgs } from "../../contracts/msgs/ILightClientMsgs.sol"; +import { IICS02ClientMsgs } from "../../contracts/msgs/IICS02ClientMsgs.sol"; +import { BesuIBFT2LightClient } from "../../contracts/light-clients/besu/BesuIBFT2LightClient.sol"; +import { BesuQBFTLightClient } from "../../contracts/light-clients/besu/BesuQBFTLightClient.sol"; +import { IBesuLightClient } from "../../contracts/light-clients/besu/interfaces/IBesuLightClient.sol"; +import { IBesuLightClientMsgs } from "../../contracts/light-clients/besu/msgs/IBesuLightClientMsgs.sol"; +import { IBesuLightClientErrors } from "../../contracts/light-clients/besu/errors/IBesuLightClientErrors.sol"; +import { RLPReader } from "../../contracts/light-clients/besu/RLPReader.sol"; + +/// @dev Successful update input and expected consensus state. +struct BesuUpdateFixture { + uint64 height; + bytes headerRlp; + uint64 trustedHeight; + bytes accountProof; + uint64 expectedTimestamp; + bytes32 expectedStorageRoot; + address[] expectedValidators; +} + +/// @dev Update input expected to be rejected. +struct BesuRejectionUpdateFixture { + uint64 height; + bytes headerRlp; + uint64 trustedHeight; + bytes accountProof; +} + +/// @dev Membership or non-membership proof and expected timestamp. +struct BesuProofFixture { + bytes proof; + uint64 proofHeight; + bytes path; + bytes value; + uint64 expectedTimestamp; +} + +/// @dev Successful or rejected update, including any scenario-specific setup. +struct BesuUpdateTestCase { + string name; + uint64 timestamp; + bytes update; + bytes preUpdate; + bytes expectedRevert; + BesuUpdateFixture expectedState; +} + +/// @dev Successful or rejected membership verification. +struct BesuMembershipTestCase { + string name; + ILightClientMsgs.MsgVerifyMembership message; + bytes expectedRevert; + uint64 expectedTimestamp; +} + +/// @dev Complete fixture shared by the Besu BFT light-client tests. +struct BesuFixture { + address routerAddress; + uint64 initialTrustedHeight; + uint64 initialTrustedTimestamp; + bytes32 initialTrustedStorageRoot; + address[] initialTrustedValidators; + uint64 trustingPeriod; + uint64 maxClockDrift; + BesuUpdateFixture adjacentUpdate; + BesuUpdateFixture nonAdjacentUpdate; + BesuRejectionUpdateFixture lowQuorumUpdate; + BesuRejectionUpdateFixture conflictingUpdate; + BesuRejectionUpdateFixture lowOverlapUpdate; + BesuProofFixture membership; + BesuProofFixture nonMembership; +} + +abstract contract BesuLightClientFixtureTestBase is Test { + using stdJson for string; + using RLPReader for bytes; + using RLPReader for RLPReader.RLPItem; + + string internal constant FIXTURE_DIR = "/test/besu-bft/fixtures/"; + + BesuFixture internal fixture; + IBesuLightClient internal client; + IBesuLightClient internal wrongWrapper; + + function setUp() public virtual { + fixture = _loadFixture(_fixtureFile()); + client = _deployPrimaryClient(); + wrongWrapper = _deployWrongWrapper(); + } + + function test_verifyNonMembership() public { + vm.warp(fixture.initialTrustedTimestamp + 1); + client.updateClient(_encodeUpdate(fixture.nonAdjacentUpdate)); + + uint256 timestamp = client.verifyNonMembership( + ILightClientMsgs.MsgVerifyNonMembership({ + proof: fixture.nonMembership.proof, + proofHeight: IICS02ClientMsgs.Height({ + revisionNumber: 0, revisionHeight: fixture.nonMembership.proofHeight + }), + path: _singlePath(fixture.nonMembership.path) + }) + ); + + assertEq(timestamp, fixture.nonMembership.expectedTimestamp); + } + + function tableUpdateClientTest(BesuUpdateTestCase memory update) public { + vm.warp(update.timestamp); + if (update.preUpdate.length != 0) { + client.updateClient(update.preUpdate); + } + + if (update.expectedRevert.length == 0) { + ILightClientMsgs.UpdateResult result = client.updateClient(update.update); + + assertEq(uint8(result), uint8(ILightClientMsgs.UpdateResult.Update)); + _assertClientState(update.expectedState); + return; + } + + bytes memory clientStateBefore = client.getClientState(); + bytes memory consensusStateBefore = client.getConsensusState(fixture.initialTrustedHeight); + + vm.expectRevert(update.expectedRevert); + client.updateClient(update.update); + + assertEq(client.getClientState(), clientStateBefore); + assertEq(client.getConsensusState(fixture.initialTrustedHeight), consensusStateBefore); + } + + function tableVerifyMembershipTest(BesuMembershipTestCase memory membership) public { + vm.warp(fixture.initialTrustedTimestamp + 1); + client.updateClient(_encodeUpdate(fixture.nonAdjacentUpdate)); + + if (membership.expectedRevert.length != 0) { + vm.expectRevert(membership.expectedRevert); + } + uint256 timestamp = client.verifyMembership(membership.message); + + if (membership.expectedRevert.length == 0) { + assertEq(timestamp, membership.expectedTimestamp); + } + } + + function test_misbehaviour_reverts() public { + vm.expectRevert(abi.encodeWithSelector(IBesuLightClientErrors.UnsupportedMisbehaviour.selector)); + client.misbehaviour(bytes("")); + } + + function test_updateClient_revertThroughWrongWrapper() public { + vm.warp(fixture.initialTrustedTimestamp + 1); + + vm.expectRevert( + abi.encodeWithSelector(IBesuLightClientErrors.InsufficientTrustedValidatorOverlap.selector, 0, 2) + ); + wrongWrapper.updateClient(_encodeUpdate(fixture.nonAdjacentUpdate)); + } + + function fixtureMembership() public view returns (BesuMembershipTestCase[] memory testCases) { + bytes[] memory path = new bytes[](2); + path[0] = fixture.membership.path; + path[1] = fixture.nonMembership.path; + + bytes memory wrongValue = abi.encodePacked(bytes32(uint256(1))); + testCases = new BesuMembershipTestCase[](4); + testCases[0] = BesuMembershipTestCase({ + name: "success", + message: _membershipMessage(0, _singlePath(fixture.membership.path), fixture.membership.value), + expectedRevert: "", + expectedTimestamp: fixture.membership.expectedTimestamp + }); + testCases[1] = BesuMembershipTestCase({ + name: "failure: wrong revision number", + message: _membershipMessage(1, _singlePath(fixture.membership.path), fixture.membership.value), + expectedRevert: abi.encodeWithSelector(IBesuLightClientErrors.InvalidRevisionNumber.selector, 1), + expectedTimestamp: 0 + }); + testCases[2] = BesuMembershipTestCase({ + name: "failure: wrong path shape", + message: _membershipMessage(0, path, fixture.membership.value), + expectedRevert: abi.encodeWithSelector(IBesuLightClientErrors.InvalidPathLength.selector, 1, 2), + expectedTimestamp: 0 + }); + testCases[3] = BesuMembershipTestCase({ + name: "failure: wrong commitment value", + message: _membershipMessage(0, _singlePath(fixture.membership.path), wrongValue), + expectedRevert: abi.encodeWithSelector( + IBesuLightClientErrors.InvalidCommitmentValue.selector, + bytes32(uint256(1)), + abi.decode(fixture.membership.value, (bytes32)) + ), + expectedTimestamp: 0 + }); + } + + function fixtureUpdate() public view returns (BesuUpdateTestCase[] memory testCases) { + BesuUpdateFixture memory emptyExpectedState; + + testCases = new BesuUpdateTestCase[](8); + testCases[0] = BesuUpdateTestCase({ + name: "success: valid adjacent update", + timestamp: fixture.initialTrustedTimestamp + 1, + update: _encodeUpdate(fixture.adjacentUpdate), + preUpdate: "", + expectedRevert: "", + expectedState: fixture.adjacentUpdate + }); + testCases[1] = BesuUpdateTestCase({ + name: "success: valid non-adjacent update", + timestamp: fixture.initialTrustedTimestamp + 1, + update: _encodeUpdate(fixture.nonAdjacentUpdate), + preUpdate: "", + expectedRevert: "", + expectedState: fixture.nonAdjacentUpdate + }); + testCases[2] = BesuUpdateTestCase({ + name: "failure: zero timestamp", + timestamp: fixture.initialTrustedTimestamp + 1, + update: _zeroTimestampUpdate(), + preUpdate: "", + expectedRevert: abi.encodeWithSelector(IBesuLightClientErrors.InvalidHeaderTimestamp.selector), + expectedState: emptyExpectedState + }); + testCases[3] = BesuUpdateTestCase({ + name: "failure: expired trusted state", + timestamp: fixture.initialTrustedTimestamp + fixture.trustingPeriod + 1, + update: _encodeUpdate(fixture.nonAdjacentUpdate), + preUpdate: "", + expectedRevert: abi.encodeWithSelector( + IBesuLightClientErrors.ConsensusStateExpired.selector, + fixture.initialTrustedTimestamp, + fixture.initialTrustedTimestamp + fixture.trustingPeriod + 1, + fixture.trustingPeriod + ), + expectedState: emptyExpectedState + }); + testCases[4] = BesuUpdateTestCase({ + name: "failure: insufficient trusted overlap", + timestamp: fixture.initialTrustedTimestamp + 1, + update: _encodeUpdate(fixture.lowOverlapUpdate), + preUpdate: "", + expectedRevert: abi.encodeWithSelector( + IBesuLightClientErrors.InsufficientTrustedValidatorOverlap.selector, 1, 2 + ), + expectedState: emptyExpectedState + }); + testCases[5] = BesuUpdateTestCase({ + name: "failure: insufficient validator quorum", + timestamp: fixture.initialTrustedTimestamp + 1, + update: _encodeUpdate(fixture.lowQuorumUpdate), + preUpdate: "", + expectedRevert: abi.encodeWithSelector(IBesuLightClientErrors.InsufficientValidatorQuorum.selector, 2, 3), + expectedState: emptyExpectedState + }); + + IBesuLightClientMsgs.MsgUpdateClient memory wrongRevisionUpdate = + abi.decode(_encodeUpdate(fixture.nonAdjacentUpdate), (IBesuLightClientMsgs.MsgUpdateClient)); + wrongRevisionUpdate.trustedHeight.revisionNumber = 1; + + testCases[6] = BesuUpdateTestCase({ + name: "failure: wrong revision number", + timestamp: fixture.initialTrustedTimestamp + 1, + update: abi.encode(wrongRevisionUpdate), + preUpdate: "", + expectedRevert: abi.encodeWithSelector(IBesuLightClientErrors.InvalidRevisionNumber.selector, 1), + expectedState: emptyExpectedState + }); + testCases[7] = BesuUpdateTestCase({ + name: "failure: conflicting same-height state", + timestamp: fixture.initialTrustedTimestamp + 1, + update: _encodeUpdate(fixture.conflictingUpdate), + preUpdate: _encodeUpdate(fixture.nonAdjacentUpdate), + expectedRevert: abi.encodeWithSelector( + IBesuLightClientErrors.ConflictingConsensusState.selector, fixture.conflictingUpdate.height + ), + expectedState: emptyExpectedState + }); + } + + function _zeroTimestampUpdate() internal view returns (bytes memory) { + BesuUpdateFixture memory update = fixture.nonAdjacentUpdate; + RLPReader.RLPItem memory headerItem = update.headerRlp.toRlpItem(); + RLPReader.RLPItem[] memory headerItems = headerItem.toList(); + (uint256 timestampPtr, uint256 timestampLen) = headerItems[11].payloadLocation(); + for (uint256 i = 0; i < timestampLen; ++i) { + update.headerRlp[timestampPtr - headerItem.memPtr + i] = 0; + } + return _encodeUpdate(update); + } + + function _assertClientState(BesuUpdateFixture memory update) internal view { + (address ibcRouter, IICS02ClientMsgs.Height memory latestHeight, uint64 trustingPeriod, uint64 maxClockDrift) = + abi.decode(client.getClientState(), (address, IICS02ClientMsgs.Height, uint64, uint64)); + assertEq(ibcRouter, fixture.routerAddress); + assertEq(latestHeight.revisionNumber, 0); + assertEq(latestHeight.revisionHeight, update.height); + assertEq(trustingPeriod, fixture.trustingPeriod); + assertEq(maxClockDrift, fixture.maxClockDrift); + + (uint64 timestamp, bytes32 storageRoot, address[] memory validators) = + abi.decode(client.getConsensusState(update.height), (uint64, bytes32, address[])); + assertEq(timestamp, update.expectedTimestamp); + assertEq(storageRoot, update.expectedStorageRoot); + + assertEq(validators.length, update.expectedValidators.length); + for (uint256 i = 0; i < update.expectedValidators.length; ++i) { + assertEq(validators[i], update.expectedValidators[i]); + } + } + + function _encodeUpdate(BesuUpdateFixture memory update) internal pure returns (bytes memory) { + return abi.encode( + IBesuLightClientMsgs.MsgUpdateClient({ + headerRlp: update.headerRlp, + trustedHeight: IICS02ClientMsgs.Height({ revisionNumber: 0, revisionHeight: update.trustedHeight }), + accountProof: update.accountProof + }) + ); + } + + function _singlePath(bytes memory path) internal pure returns (bytes[] memory out) { + out = new bytes[](1); + out[0] = path; + } + + function _membershipMessage( + uint64 revisionNumber, + bytes[] memory path, + bytes memory value + ) + internal + view + returns (ILightClientMsgs.MsgVerifyMembership memory) + { + return ILightClientMsgs.MsgVerifyMembership({ + proof: fixture.membership.proof, + proofHeight: IICS02ClientMsgs.Height({ + revisionNumber: revisionNumber, revisionHeight: fixture.membership.proofHeight + }), + path: path, + value: value + }); + } + + function _loadFixture(string memory fileName) internal view returns (BesuFixture memory) { + string memory root = vm.projectRoot(); + string memory path = string.concat(root, FIXTURE_DIR, fileName); + string memory json = vm.readFile(path); + + return BesuFixture({ + routerAddress: json.readAddress(".routerAddress"), + initialTrustedHeight: uint64(json.readUint(".initialTrustedHeight")), + initialTrustedTimestamp: uint64(json.readUint(".initialTrustedTimestamp")), + initialTrustedStorageRoot: json.readBytes32(".initialTrustedStorageRoot"), + initialTrustedValidators: abi.decode(json.parseRaw(".initialTrustedValidators"), (address[])), + trustingPeriod: uint64(json.readUint(".trustingPeriod")), + maxClockDrift: uint64(json.readUint(".maxClockDrift")), + adjacentUpdate: _readUpdate(json, ".adjacentUpdate"), + nonAdjacentUpdate: _readUpdate(json, ".nonAdjacentUpdate"), + lowQuorumUpdate: _readRejectionUpdate(json, ".lowQuorumUpdate"), + conflictingUpdate: _readRejectionUpdate(json, ".conflictingUpdate"), + lowOverlapUpdate: _readRejectionUpdate(json, ".lowOverlapUpdate"), + membership: _readProof(json, ".membership"), + nonMembership: _readProof(json, ".nonMembership") + }); + } + + function _readUpdate(string memory json, string memory path) internal pure returns (BesuUpdateFixture memory) { + return BesuUpdateFixture({ + height: uint64(json.readUint(string.concat(path, ".height"))), + headerRlp: json.readBytes(string.concat(path, ".headerRlp")), + trustedHeight: uint64(json.readUint(string.concat(path, ".trustedHeight"))), + accountProof: json.readBytes(string.concat(path, ".accountProof")), + expectedTimestamp: uint64(json.readUint(string.concat(path, ".expectedTimestamp"))), + expectedStorageRoot: json.readBytes32(string.concat(path, ".expectedStorageRoot")), + expectedValidators: abi.decode(json.parseRaw(string.concat(path, ".expectedValidators")), (address[])) + }); + } + + function _readRejectionUpdate( + string memory json, + string memory path + ) + internal + pure + returns (BesuRejectionUpdateFixture memory) + { + return BesuRejectionUpdateFixture({ + height: uint64(json.readUint(string.concat(path, ".height"))), + headerRlp: json.readBytes(string.concat(path, ".headerRlp")), + trustedHeight: uint64(json.readUint(string.concat(path, ".trustedHeight"))), + accountProof: json.readBytes(string.concat(path, ".accountProof")) + }); + } + + function _encodeUpdate(BesuRejectionUpdateFixture memory update) internal pure returns (bytes memory) { + return abi.encode( + IBesuLightClientMsgs.MsgUpdateClient({ + headerRlp: update.headerRlp, + trustedHeight: IICS02ClientMsgs.Height({ revisionNumber: 0, revisionHeight: update.trustedHeight }), + accountProof: update.accountProof + }) + ); + } + + function _readProof(string memory json, string memory path) internal view returns (BesuProofFixture memory) { + return BesuProofFixture({ + proof: json.readBytes(string.concat(path, ".proof")), + proofHeight: uint64(json.readUint(string.concat(path, ".proofHeight"))), + path: json.readBytes(string.concat(path, ".path")), + value: json.keyExists(string.concat(path, ".value")) + ? json.readBytes(string.concat(path, ".value")) + : bytes(""), + expectedTimestamp: uint64(json.readUint(string.concat(path, ".expectedTimestamp"))) + }); + } + + function _deployIBFT2() internal returns (IBesuLightClient) { + return new BesuIBFT2LightClient( + fixture.routerAddress, + fixture.initialTrustedHeight, + fixture.initialTrustedTimestamp, + fixture.initialTrustedStorageRoot, + fixture.initialTrustedValidators, + fixture.trustingPeriod, + fixture.maxClockDrift, + address(0) + ); + } + + function _deployQBFT() internal returns (IBesuLightClient) { + return new BesuQBFTLightClient( + fixture.routerAddress, + fixture.initialTrustedHeight, + fixture.initialTrustedTimestamp, + fixture.initialTrustedStorageRoot, + fixture.initialTrustedValidators, + fixture.trustingPeriod, + fixture.maxClockDrift, + address(0) + ); + } + + function _fixtureFile() internal pure virtual returns (string memory); + function _deployPrimaryClient() internal virtual returns (IBesuLightClient); + function _deployWrongWrapper() internal virtual returns (IBesuLightClient); +} diff --git a/ibc-solidity/test/besu-bft/BesuLightClientQuorum.t.sol b/ibc-solidity/test/besu-bft/BesuLightClientQuorum.t.sol new file mode 100644 index 000000000..9a949da2b --- /dev/null +++ b/ibc-solidity/test/besu-bft/BesuLightClientQuorum.t.sol @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.28; + +import { Test } from "forge-std/Test.sol"; + +import { BesuLightClientBase } from "../../contracts/light-clients/besu/BesuLightClientBase.sol"; +import { IBesuLightClientErrors } from "../../contracts/light-clients/besu/errors/IBesuLightClientErrors.sol"; + +contract BesuLightClientQuorumHarness is BesuLightClientBase { + constructor( + uint64 initialTrustedTimestamp, + address[] memory initialValidators + ) + BesuLightClientBase(address(1), 1, initialTrustedTimestamp, bytes32(0), initialValidators, 0, 0, address(0)) + { } + + function checkValidatorQuorum(address[] calldata signers, address[] calldata validators) external pure { + _checkValidatorQuorum(signers, validators); + } + + function _commitSealDigest(ParsedHeader memory) internal pure override returns (bytes32) { + return bytes32(0); + } +} + +contract BesuLightClientQuorumTest is Test { + BesuLightClientQuorumHarness private harness; + + function setUp() public { + harness = new BesuLightClientQuorumHarness(1, _addresses(1)); + } + + function test_constructor_rejectsZeroTrustedTimestamp() public { + vm.expectRevert(IBesuLightClientErrors.InvalidHeaderTimestamp.selector); + new BesuLightClientQuorumHarness(0, _addresses(1)); + } + + function test_checkValidatorQuorum_acceptsBesuFourOfSixQuorum() public view { + harness.checkValidatorQuorum(_addresses(4), _addresses(6)); + } + + function test_checkValidatorQuorum_rejectsThreeOfSixValidators() public { + vm.expectRevert(abi.encodeWithSelector(IBesuLightClientErrors.InsufficientValidatorQuorum.selector, 3, 4)); + harness.checkValidatorQuorum(_addresses(3), _addresses(6)); + } + + function _addresses(uint256 length) private pure returns (address[] memory addresses) { + addresses = new address[](length); + for (uint256 i = 0; i < length; ++i) { + addresses[i] = address(uint160(i + 1)); + } + } +} diff --git a/ibc-solidity/test/besu-bft/BesuQBFTLightClient.t.sol b/ibc-solidity/test/besu-bft/BesuQBFTLightClient.t.sol new file mode 100644 index 000000000..1b67f785b --- /dev/null +++ b/ibc-solidity/test/besu-bft/BesuQBFTLightClient.t.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.28; + +import { IBesuLightClient } from "../../contracts/light-clients/besu/interfaces/IBesuLightClient.sol"; +import { BesuLightClientFixtureTestBase } from "./BesuLightClientFixtureTestBase.sol"; + +contract BesuQBFTLightClientTest is BesuLightClientFixtureTestBase { + function _fixtureFile() internal pure override returns (string memory) { + return "qbft.json"; + } + + function _deployPrimaryClient() internal override returns (IBesuLightClient) { + return _deployQBFT(); + } + + function _deployWrongWrapper() internal override returns (IBesuLightClient) { + return _deployIBFT2(); + } +} diff --git a/ibc-solidity/test/besu-bft/fixtures/ibft2.json b/ibc-solidity/test/besu-bft/fixtures/ibft2.json new file mode 100644 index 000000000..57136043b --- /dev/null +++ b/ibc-solidity/test/besu-bft/fixtures/ibft2.json @@ -0,0 +1,97 @@ +{ + "routerAddress": "0x1234567890AbcdEF1234567890aBcdef12345678", + "initialTrustedHeight": 10, + "initialTrustedTimestamp": 1000, + "initialTrustedStorageRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "initialTrustedValidators": [ + "0xFE3B557E8Fb62b89F4916B721be55cEb828dBd73", + "0x627306090abaB3A6e1400e9345bC60c78a8BEf57", + "0xf17f52151EbEF6C7334FAD080c5704D77216b732", + "0xa89F47C6b463f74d87572b058427dA0A13ec5425" + ], + "trustingPeriod": 1000, + "maxClockDrift": 30, + "adjacentUpdate": { + "height": 11, + "headerRlp": "0xf9033ca00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0f2081dd8c37a93ef3050951656b124dba1eb1e541e52e98c8bbbac27611bae73a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010b8401c9c380808203f2b90147f90144a00000000000000000000000000000000000000000000000000000000000000000f85494fe3b557e8fb62b89f4916b721be55ceb828dbd7394627306090abab3a6e1400e9345bc60c78a8bef5794f17f52151ebef6c7334fad080c5704d77216b73294a89f47c6b463f74d87572b058427da0a13ec54258080f8c9b8415c237229535cb5b756ac35933bd6460128d8358af7224b3d373bc1e58671b9e26ddd5f2f6318493978a02162192da231068943ef7d31f3d49a99912245c8933300b841737d327b80cc8c318cfc223a801b7d51f17a3e61a008ba796c9a8128c13f3a6f5d36764ac0aa1f4cf788d18831193962a7f4bd42e4356bc2d2cd6795d1cc29cd01b841681d75e13f57e972a3c7696b2ff358722ab0b5d0878095146fdb03a7a688975814d97fac43069952f0382aee020d77f554f4a31e502259e28c271f748e1c113e01a063746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365880000000000000000", + "trustedHeight": 10, + "accountProof": "0xf86cf86aa1205f6174255b44b7ca652c5289d2546de65e4394eb6aa52a40045e01237736d023b846f8440180a01429811e8e479d4d8d3862e6da4c368715f6574d307bb0ffbea0220c2351cfd4a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "expectedTimestamp": 1010, + "expectedStorageRoot": "0x1429811e8e479d4d8d3862e6da4c368715f6574d307bb0ffbea0220c2351cfd4", + "expectedValidators": [ + "0xFE3B557E8Fb62b89F4916B721be55cEb828dBd73", + "0x627306090abaB3A6e1400e9345bC60c78a8BEf57", + "0xf17f52151EbEF6C7334FAD080c5704D77216b732", + "0xa89F47C6b463f74d87572b058427dA0A13ec5425" + ] + }, + "nonAdjacentUpdate": { + "height": 12, + "headerRlp": "0xf9033ca00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0f4fb47fab37d2702f85f5562b52da4e7b5e4a677298193c9f797e467e9cc046aa00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010c8401c9c380808203fcb90147f90144a00000000000000000000000000000000000000000000000000000000000000000f85494fe3b557e8fb62b89f4916b721be55ceb828dbd7394627306090abab3a6e1400e9345bc60c78a8bef5794f17f52151ebef6c7334fad080c5704d77216b73294cbed645b1c1a6254f1149df51d3591c6b38030078080f8c9b84100eaa1df128060399277424940a4cccd0ceb29052f83358f1798cf9ad95c0f0c3e858beb37cd83332935b0927d2365e439a9b1c319bf0a0adaf2f62d61dff58901b841c4bf6688b64aa46676b969e679ed39c1a0b2ae13f8c7e49ff34629f49b03bb1336a7e049716855a50a637c49dbd01d576571ef9294335623d4d42ef3b184e73601b8412df49de5d8c13913300fd9ebd1d70d76ce9f73f26e122e451c464031744f079a438762535d0e5cc031383599d8b85ae91bff81d4d10980262f70ec6ed82666f700a063746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365880000000000000000", + "trustedHeight": 10, + "accountProof": "0xf86cf86aa1205f6174255b44b7ca652c5289d2546de65e4394eb6aa52a40045e01237736d023b846f8440180a04ec23ab75bd034f079225053b7f607981b27ad24a5e964743526eeccefc5f500a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "expectedTimestamp": 1020, + "expectedStorageRoot": "0x4ec23ab75bd034f079225053b7f607981b27ad24a5e964743526eeccefc5f500", + "expectedValidators": [ + "0xFE3B557E8Fb62b89F4916B721be55cEb828dBd73", + "0x627306090abaB3A6e1400e9345bC60c78a8BEf57", + "0xf17f52151EbEF6C7334FAD080c5704D77216b732", + "0xcBED645B1C1a6254f1149Df51d3591c6B3803007" + ] + }, + "lowQuorumUpdate": { + "height": 12, + "headerRlp": "0xf902f9a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0f4fb47fab37d2702f85f5562b52da4e7b5e4a677298193c9f797e467e9cc046aa00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010c8401c9c380808203fcb90104f90101a00000000000000000000000000000000000000000000000000000000000000000f85494fe3b557e8fb62b89f4916b721be55ceb828dbd7394627306090abab3a6e1400e9345bc60c78a8bef5794f17f52151ebef6c7334fad080c5704d77216b73294cbed645b1c1a6254f1149df51d3591c6b38030078080f886b84100eaa1df128060399277424940a4cccd0ceb29052f83358f1798cf9ad95c0f0c3e858beb37cd83332935b0927d2365e439a9b1c319bf0a0adaf2f62d61dff58901b841c4bf6688b64aa46676b969e679ed39c1a0b2ae13f8c7e49ff34629f49b03bb1336a7e049716855a50a637c49dbd01d576571ef9294335623d4d42ef3b184e73601a063746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365880000000000000000", + "trustedHeight": 10, + "accountProof": "0xf86cf86aa1205f6174255b44b7ca652c5289d2546de65e4394eb6aa52a40045e01237736d023b846f8440180a04ec23ab75bd034f079225053b7f607981b27ad24a5e964743526eeccefc5f500a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "expectedTimestamp": 1020, + "expectedStorageRoot": "0x4ec23ab75bd034f079225053b7f607981b27ad24a5e964743526eeccefc5f500", + "expectedValidators": [ + "0xFE3B557E8Fb62b89F4916B721be55cEb828dBd73", + "0x627306090abaB3A6e1400e9345bC60c78a8BEf57", + "0xf17f52151EbEF6C7334FAD080c5704D77216b732", + "0xcBED645B1C1a6254f1149Df51d3591c6B3803007" + ] + }, + "conflictingUpdate": { + "height": 12, + "headerRlp": "0xf9033ca00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a002920b43c148d62cc879e6d86a0fea5cb5f6e9d5bc65b85f012955ddcf82b134a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010c8401c9c380808203fdb90147f90144a00000000000000000000000000000000000000000000000000000000000000000f85494fe3b557e8fb62b89f4916b721be55ceb828dbd7394627306090abab3a6e1400e9345bc60c78a8bef5794f17f52151ebef6c7334fad080c5704d77216b73294cbed645b1c1a6254f1149df51d3591c6b38030078080f8c9b8416f5732f70922c0ca46fc2bd56db36c79b7cc9da2b73f56513703b8daaf75001a1907b11de095b3ba30413d17584b7d448414ea87872609d89f264d76eb3c2bd800b8411ef65e4f2a8d80933195e7b1a1451fa114e9cfb44fe6c89688a73f0a77b72f04701d0de8cb85fcc7347ba5dc6e066bb14ff77bdcc582ed1cba0cc902ba0c698d01b841464fc7ac400db011dbfe93fe8ff28dfc13f94074c5225bfd0b63827d5dc40eb335d3982bdf385f569d668844155121ce0b74d681e914d79392b492698d10611800a063746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365880000000000000000", + "trustedHeight": 10, + "accountProof": "0xf86cf86aa1205f6174255b44b7ca652c5289d2546de65e4394eb6aa52a40045e01237736d023b846f8440180a05cc3ae2f35df83cafbdd6f6220a2eceb3e7ef6c9e10df3787bd8e9d5deae1f92a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "expectedTimestamp": 1021, + "expectedStorageRoot": "0x5cc3ae2f35df83cafbdd6f6220a2eceb3e7ef6c9e10df3787bd8e9d5deae1f92", + "expectedValidators": [ + "0xFE3B557E8Fb62b89F4916B721be55cEb828dBd73", + "0x627306090abaB3A6e1400e9345bC60c78a8BEf57", + "0xf17f52151EbEF6C7334FAD080c5704D77216b732", + "0xcBED645B1C1a6254f1149Df51d3591c6B3803007" + ] + }, + "lowOverlapUpdate": { + "height": 13, + "headerRlp": "0xf9033ca00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a00d2546fbdd16af694bb1e7a28440bd1d56197e4eb349532dba3b0b71778ac051a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010d8401c9c38080820406b90147f90144a00000000000000000000000000000000000000000000000000000000000000000f85494fe3b557e8fb62b89f4916b721be55ceb828dbd7394cbed645b1c1a6254f1149df51d3591c6b38030079400731540cd6060991d6b9c57ce295998d9bc2fab947e5f4552091a69125d5dfcb7b8c2659029395bdf8080f8c9b841ae4e5c4cd1f82a1d962f8ffde7c51396f2ac85fe4d3cc9b9a5eb249c1c3850665faa295fa6c0444025cc66b4e7d18b4b8469f3f851e735744babc3a99a12b58201b84194c7c8462d7d74c9bfd80f0e62b76a49316f2a0075ec7df65fb207d2c0eb75801f01c30b6a4f0445cb1cb8936d9f27587575449c1e25b17338c91eba6ac6a43301b841b854f80b9675f6b1f403b0c415ea6780f46e76d7c744f2d4d93004f4cdc533420efd490dcb0a80f298e6046ce974c64a45dab9cf86022bd478588e4f405b3e3d00a063746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365880000000000000000", + "trustedHeight": 10, + "accountProof": "0xf86cf86aa1205f6174255b44b7ca652c5289d2546de65e4394eb6aa52a40045e01237736d023b846f8440180a05dd23a6a8429ec8af97267494c6fa465682207585232c1ac7cd53eb9fd1b0318a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "expectedTimestamp": 1030, + "expectedStorageRoot": "0x5dd23a6a8429ec8af97267494c6fa465682207585232c1ac7cd53eb9fd1b0318", + "expectedValidators": [ + "0xFE3B557E8Fb62b89F4916B721be55cEb828dBd73", + "0xcBED645B1C1a6254f1149Df51d3591c6B3803007", + "0x00731540cd6060991D6B9C57CE295998d9bC2faB", + "0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf" + ] + }, + "membership": { + "proof": "0xf846f844a1203bd6be3bff117383e9ac885fff068af75120fde9a2c812e23878d38cce456852a1a0ac99c4edfa8056f2d49a30515770881f02a4f118254da280fe00dbcd0f54e876", + "proofHeight": 12, + "path": "0x636c69656e742d6f6e2d62657375010000000000000007", + "value": "0xac99c4edfa8056f2d49a30515770881f02a4f118254da280fe00dbcd0f54e876", + "expectedTimestamp": 1020 + }, + "nonMembership": { + "proof": "0xf846f844a1203bd6be3bff117383e9ac885fff068af75120fde9a2c812e23878d38cce456852a1a0ac99c4edfa8056f2d49a30515770881f02a4f118254da280fe00dbcd0f54e876", + "proofHeight": 12, + "path": "0x636c69656e742d6f6e2d62657375020000000000000007", + "expectedTimestamp": 1020 + } +} diff --git a/ibc-solidity/test/besu-bft/fixtures/qbft.json b/ibc-solidity/test/besu-bft/fixtures/qbft.json new file mode 100644 index 000000000..6019bd0ca --- /dev/null +++ b/ibc-solidity/test/besu-bft/fixtures/qbft.json @@ -0,0 +1,73 @@ +{ + "routerAddress": "0x07A6F66Beb52276B247A79B7B9D43416F9855f42", + "initialTrustedHeight": 33, + "initialTrustedTimestamp": 1787357305, + "initialTrustedStorageRoot": "0x2f39a2a5a30e1d6251aa6cbe8e47d8f8e2f01ebf00fb76e96abf17f5555089fc", + "initialTrustedValidators": [ + "0x065f139d8A49E9926232Cc4435159024cb5064FC", + "0x0EB968DE631aBC65322EcDCa5DfDF9C6296e52f4", + "0x20C5eDBCf6263Cd9E30Df395A2B914F6E939B9Ba", + "0x543d3796700eE35803A1C43562a69FEc08E1e423" + ], + "trustingPeriod": 1209600, + "maxClockDrift": 15, + "adjacentUpdate": { + "height": 34, + "headerRlp": "0xf90385a07ee4185f15b458dcff8936e722e3792ddf28a3f6801ce06374969f54031b762aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479420c5edbcf6263cd9e30df395a2b914f6e939b9baa030defd9bc19472d5ccbb248e391b49320a77fd71652b0bafeddb78725ef28515a078e6f2f4fe203157e3d5c67a75ce82947103e360cc17f0a3d60e38b6c552a08aa00149f44a46b46c6429cf561eda5e72322b31debaa8ff69357298cb2e8206a524b901001000000000000000000000000004000000000000000000000000000000000000008000000000000010000000000000000000000000000000000000000020000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000002008000000000000000000000000020000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001228402faf08082b349846a88e87bb90147f90144a0000000000000000000000000000000000000000000626573752032362e342e30f85494065f139d8a49e9926232cc4435159024cb5064fc940eb968de631abc65322ecdca5dfdf9c6296e52f49420c5edbcf6263cd9e30df395a2b914f6e939b9ba94543d3796700ee35803a1c43562a69fec08e1e423c080f8c9b8410e4196ae86251b9ad1f92ccd0deb5c615f5d5f55d32fd232b303bdd8e18c6e806ee612e50f641ec37026ccfb294ed1631bf0c7eac49b710fe2e66fd4082d356401b841e0646ce5a4c2005b25d182bbdd0c22022156e007d243699b9f928d58e6cd9ffe6613aaf033ec261c48c224fa1cba87886161aae03362de1fcc3871b3da3c70f600b84142ce15667100923022aa210debed209729367078b1fc71108f8dcfaa7c102032012fb03c701e8c854062fb4281e9dda4509932121a33dbb79ec0a47a4f738ff800a063746963616c2062797a616e74696e65206661756c7420746f6c6572616e636588000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000", + "trustedHeight": 33, + "accountProof": "0xf902b2f901f1a0886aec3477fe3ac6276485bfaf3e5e1eea382e6911831691f50c734edcea799e80a08573bfe9264ed8b6afc58b400efeaae64f1d56bc8396d44a2dcfd17a9c14b7a2a092450fe708c280f7c52ea0eeb14974139fd3d4dcc7cc77a37fcafbe187480ea3a01d272d6cf8f93bc15533e54ea3f459a982fc32e1272d95cf1d0cde1361463cfda0682e0509d82289dcb84f9d366ed881bfe4655d3c15de298e3d6fe4183d7051cca0e8fbbb10bb2183848e739cd3654a1ff083ca953bee3b58fd56b063f810cf1722a074a59b1b84fc35ff94e4f762b894b113da5941ca99e21df30783140f4a33b1cca0014abed6a424575260405210754b1aa0d4cabe50e8616ac231e424973fc0a895a08d662e3f7d019145626a3d1e9d29c1ce0a98d49c8cd6a5c85398f6acbe83e23ea0397a811f344f0827d373cddaaac7063a83ed8a127e56864b2491774c97d01912a0ccca73c8748a8ec56ef293bee631a7d21ef1e1ec8b053e976f6ef3faa50187fba0613dbbef57a2660c21ec8c864749de69ac0bc4b59f6aef6477a090fdd51f467aa090c93d47b38631bbdc1156f9e0caa1eaaf5bd87827b8535e097ad48b274bc01ca05edc383ad614e86f1da2e1a91d7e85ae5ab1d098a0d47623ef13d49d02754f8ea0c345faa773370853ac7afa5d32956ce53465ceac1e060e424343b39d9793397680f8518080a065c2085561952935fde3dfd4a299d8d01d46529c6d3f69aaac4134c61e4cab3a808080808080808080a0df2fc47ed0c87770a1fbcd193fbba94e57e0aa2a3d3960a8daa84dd1fc39d76e80808080f869a020b221f4fe86714230ec6dfaf784ee106a9f8901d542e537af01e28564065574b846f8440180a02f39a2a5a30e1d6251aa6cbe8e47d8f8e2f01ebf00fb76e96abf17f5555089fca07f79b8b370510aa3a9ea8536a9459c92de9493272cd5fe45c02364cfe254a9a7", + "expectedTimestamp": 1787357307, + "expectedStorageRoot": "0x2f39a2a5a30e1d6251aa6cbe8e47d8f8e2f01ebf00fb76e96abf17f5555089fc", + "expectedValidators": [ + "0x065f139d8A49E9926232Cc4435159024cb5064FC", + "0x0EB968DE631aBC65322EcDCa5DfDF9C6296e52f4", + "0x20C5eDBCf6263Cd9E30Df395A2B914F6E939B9Ba", + "0x543d3796700eE35803A1C43562a69FEc08E1e423" + ] + }, + "nonAdjacentUpdate": { + "height": 35, + "headerRlp": "0xf90386a0e8eb81a5cc7e4bc105561f792aed8d6ed967305e1460902b48544d9198519a65a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794543d3796700ee35803a1c43562a69fec08e1e423a00bcab205a2b4819b25f76797dc4582c3818a56731f31904884f817a1a27fa442a0faa58af4eab20011acc6e66b20b1bc8a8d8b444e62e76b6e49fa790284a6538fa08e05526631e8b9e7f21d1d65cfdef62d8ac6d6d11050db08db39741243eed4eeb901001000000000000008800000000004000000000000000000001000000000000000008000000000000010000000000000400000040000000000000000000204000000000040000000000000020800100400800000000004100000000002000000000000000000000000800001000000000000000008000000000000001000000000000000000000100000080000000008000800000000008000000000000000000000000000000000000004000000000000000000000000000000000000000000000010000200000000000010004000000000000000000400000080000000004000000000000000000000000800000008000000000000000000000000000000000001238402faf0808306784b846a88e87db90147f90144a0000000000000000000000000000000000000000000626573752032362e342e30f85494065f139d8a49e9926232cc4435159024cb5064fc940eb968de631abc65322ecdca5dfdf9c6296e52f49420c5edbcf6263cd9e30df395a2b914f6e939b9ba94543d3796700ee35803a1c43562a69fec08e1e423c080f8c9b841eae1fc67c37231c16d0db99ee0b2ef4e72351cccfad04fac8cd3a425e4adf73660f50280839ad121cbc89d352bb2b199b4ee44edfe19db2321933daedd261d9900b841328d044bbe376b4be8495b33faebea0bbfaf40f9c37604ef9d8fe49243cf7f4f2274fafe780d9a0d63e5177f25ecb4fa40382e767856a424467102ef8795530a01b841ad76a8c3edacc84e6341df92e64b3e1756c90bd8cb0d5c9194bf330c80da5e217ec191891813deb925a4b2d012cf919e561ac37359f1788abc589042ac115d9001a063746963616c2062797a616e74696e65206661756c7420746f6c6572616e636588000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000", + "trustedHeight": 33, + "accountProof": "0xf902b2f901f1a0886aec3477fe3ac6276485bfaf3e5e1eea382e6911831691f50c734edcea799e80a08573bfe9264ed8b6afc58b400efeaae64f1d56bc8396d44a2dcfd17a9c14b7a2a0174fa4f59759c5446865fa6777e34929c1bc09c97412a84c064dd7864ed625e7a01d272d6cf8f93bc15533e54ea3f459a982fc32e1272d95cf1d0cde1361463cfda0682e0509d82289dcb84f9d366ed881bfe4655d3c15de298e3d6fe4183d7051cca0bbb94f73543a77ce1f2e90a6ab92e5a6911e5af84dc8e1bcc33a0b20e10a2c5ba0fd265a27de5e8596bb6acaaf60ace61e3a9e724f75a7543af8b738754199998fa0014abed6a424575260405210754b1aa0d4cabe50e8616ac231e424973fc0a895a060bd3b16ddfd75eae7933b7d0dbf717adb2c8b16573d4706eec89b33a71be71ca00e4d3a60002f359ab48688dc19ebd727bccb488984e27264d91bcba10302b7faa0ccca73c8748a8ec56ef293bee631a7d21ef1e1ec8b053e976f6ef3faa50187fba0613dbbef57a2660c21ec8c864749de69ac0bc4b59f6aef6477a090fdd51f467aa090c93d47b38631bbdc1156f9e0caa1eaaf5bd87827b8535e097ad48b274bc01ca05edc383ad614e86f1da2e1a91d7e85ae5ab1d098a0d47623ef13d49d02754f8ea0c345faa773370853ac7afa5d32956ce53465ceac1e060e424343b39d9793397680f8518080a090a8eabac86b7acb55ccec8235f1372ffaa1bd13b53a97089bc04c4f48fb0620808080808080808080a0df2fc47ed0c87770a1fbcd193fbba94e57e0aa2a3d3960a8daa84dd1fc39d76e80808080f869a020b221f4fe86714230ec6dfaf784ee106a9f8901d542e537af01e28564065574b846f8440180a04bbf8536a690306e276e29d183d17b249edb483a00dd9ad732552be38f8e6301a07f79b8b370510aa3a9ea8536a9459c92de9493272cd5fe45c02364cfe254a9a7", + "expectedTimestamp": 1787357309, + "expectedStorageRoot": "0x4bbf8536a690306e276e29d183d17b249edb483a00dd9ad732552be38f8e6301", + "expectedValidators": [ + "0x065f139d8A49E9926232Cc4435159024cb5064FC", + "0x0EB968DE631aBC65322EcDCa5DfDF9C6296e52f4", + "0x20C5eDBCf6263Cd9E30Df395A2B914F6E939B9Ba", + "0x543d3796700eE35803A1C43562a69FEc08E1e423" + ] + }, + "lowQuorumUpdate": { + "height": 35, + "headerRlp": "0xf90343a0e8eb81a5cc7e4bc105561f792aed8d6ed967305e1460902b48544d9198519a65a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794543d3796700ee35803a1c43562a69fec08e1e423a00bcab205a2b4819b25f76797dc4582c3818a56731f31904884f817a1a27fa442a0faa58af4eab20011acc6e66b20b1bc8a8d8b444e62e76b6e49fa790284a6538fa08e05526631e8b9e7f21d1d65cfdef62d8ac6d6d11050db08db39741243eed4eeb901001000000000000008800000000004000000000000000000001000000000000000008000000000000010000000000000400000040000000000000000000204000000000040000000000000020800100400800000000004100000000002000000000000000000000000800001000000000000000008000000000000001000000000000000000000100000080000000008000800000000008000000000000000000000000000000000000004000000000000000000000000000000000000000000000010000200000000000010004000000000000000000400000080000000004000000000000000000000000800000008000000000000000000000000000000000001238402faf0808306784b846a88e87db90104f90101a0000000000000000000000000000000000000000000626573752032362e342e30f85494065f139d8a49e9926232cc4435159024cb5064fc940eb968de631abc65322ecdca5dfdf9c6296e52f49420c5edbcf6263cd9e30df395a2b914f6e939b9ba94543d3796700ee35803a1c43562a69fec08e1e423c080f886b841eae1fc67c37231c16d0db99ee0b2ef4e72351cccfad04fac8cd3a425e4adf73660f50280839ad121cbc89d352bb2b199b4ee44edfe19db2321933daedd261d9900b841328d044bbe376b4be8495b33faebea0bbfaf40f9c37604ef9d8fe49243cf7f4f2274fafe780d9a0d63e5177f25ecb4fa40382e767856a424467102ef8795530a01a063746963616c2062797a616e74696e65206661756c7420746f6c6572616e636588000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000", + "trustedHeight": 33, + "accountProof": "0x" + }, + "conflictingUpdate": { + "height": 35, + "headerRlp": "0xf90386a084d5dbd206ef4a465f66c8b14ce809687baa221677a986bc15ec5b99b8579e8da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794065f139d8a49e9926232cc4435159024cb5064fca02bbf0aa2342ab306dda9aa494f3ffe8a2fb2ebd327bf99fe2f4609e5d56a287fa0ede1198cf1f6072bfe88d1beabbbb3ceefda3094b5b6ca1aa0e50e5aa58d5aa0a0c2f035f70c9a89c2f0fbf3b4fad07d005b637eaaf0ae084de4a189de91414442b901000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000400000000000000000000000000204000000000000000000000000000008000000000000000004000000000002000000000000000000000000000000000000000200000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000100000000000004000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000004000000000200000000000000000000000000000000000000000000000000000000001238402faf080830b245a846a88e87fb90147f90144a0000000000000000000000000000000000000000000626573752032362e342e30f85494065f139d8a49e9926232cc4435159024cb5064fc940eb968de631abc65322ecdca5dfdf9c6296e52f49420c5edbcf6263cd9e30df395a2b914f6e939b9ba94543d3796700ee35803a1c43562a69fec08e1e423c080f8c9b841fa5785d98739747d89cb99b923440ce46a4d1c66c9cf9d1171a6b70bbaeeecf3000da2ce63d7c7e284da788bade5423ad89ca27b009cc5ab25f3d164e829b6bd01b841b05d0d27772ddb76da6b8094d099b4e6b158290825c7756f583be9fa887f0c9d528cb2cdfaa9147dbca6f947a97e488226bc4e0253a6f8a724b2b2a8eecd16fc00b8419e75966c499c86f1178194190c747387a0e70cdb7eb0a826896b66781fe381074df6b59ae6320464d9c5ad6417157390a8278bded19f5965b110edf22f684af500a063746963616c2062797a616e74696e65206661756c7420746f6c6572616e636588000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000", + "trustedHeight": 33, + "accountProof": "0xf902b2f901f1a0886aec3477fe3ac6276485bfaf3e5e1eea382e6911831691f50c734edcea799e80a08573bfe9264ed8b6afc58b400efeaae64f1d56bc8396d44a2dcfd17a9c14b7a2a0174fa4f59759c5446865fa6777e34929c1bc09c97412a84c064dd7864ed625e7a01d272d6cf8f93bc15533e54ea3f459a982fc32e1272d95cf1d0cde1361463cfda0682e0509d82289dcb84f9d366ed881bfe4655d3c15de298e3d6fe4183d7051cca0f9b17a214dc86111bc5c9310d57aac2486dd4eda6ae8da9caa0bb2185b4015b9a060613dc1091a24ed1576c9103e09c5267bf509441384562347123960d496cc8ba0014abed6a424575260405210754b1aa0d4cabe50e8616ac231e424973fc0a895a060bd3b16ddfd75eae7933b7d0dbf717adb2c8b16573d4706eec89b33a71be71ca00e4d3a60002f359ab48688dc19ebd727bccb488984e27264d91bcba10302b7faa0ccca73c8748a8ec56ef293bee631a7d21ef1e1ec8b053e976f6ef3faa50187fba0613dbbef57a2660c21ec8c864749de69ac0bc4b59f6aef6477a090fdd51f467aa034d7ac756aa6ef347f0e3dc9a6f4db4409baca5d1e7d75dbff0842795d3b3d11a05edc383ad614e86f1da2e1a91d7e85ae5ab1d098a0d47623ef13d49d02754f8ea0c345faa773370853ac7afa5d32956ce53465ceac1e060e424343b39d9793397680f8518080a0f3ae7979f8d7015e2141c041cec64bc388a9362583c0e9014baec75c098bbe24808080808080808080a0df2fc47ed0c87770a1fbcd193fbba94e57e0aa2a3d3960a8daa84dd1fc39d76e80808080f869a020b221f4fe86714230ec6dfaf784ee106a9f8901d542e537af01e28564065574b846f8440180a061734a2ddcb2c34ad14a2bb4f7326dc4fa7e4dd4c6be97ba2e2d2fdd03b77f20a07f79b8b370510aa3a9ea8536a9459c92de9493272cd5fe45c02364cfe254a9a7" + }, + "lowOverlapUpdate": { + "height": 36, + "headerRlp": "0xf90386a084d5dbd206ef4a465f66c8b14ce809687baa221677a986bc15ec5b99b8579e8da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794065f139d8a49e9926232cc4435159024cb5064fca02bbf0aa2342ab306dda9aa494f3ffe8a2fb2ebd327bf99fe2f4609e5d56a287fa0ede1198cf1f6072bfe88d1beabbbb3ceefda3094b5b6ca1aa0e50e5aa58d5aa0a0c2f035f70c9a89c2f0fbf3b4fad07d005b637eaaf0ae084de4a189de91414442b901000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000400000000000000000000000000204000000000000000000000000000008000000000000000004000000000002000000000000000000000000000000000000000200000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000100000000000004000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000004000000000200000000000000000000000000000000000000000000000000000000001248402faf080830b245a846a88e87fb90147f90144a0000000000000000000000000000000000000000000626573752032362e342e30f85494065f139d8a49e9926232cc4435159024cb5064fc9446a5b7e742f9ad777ef8bb85aebc717e7433dc47946af3e238490ca4b6ae4f1efdf12c04cc160423c3941780ffe5324fe74e6f2ef012edc9bd205e74555bc080f8c9b8411abc319e0b1a343bf29a207a0369df6b6869c7cd07611807e5ad78e514033fa700cafa3268fba741f02366e7fa5fb7c86074a5edac1da2b602a77f3b81bb33fa00b841f58c52cac0586900e5222700194f1c1745d0d1840f8e7f69b9cc3739da58d67a680b35b14ca35a8cc997e8cc8f05a22503349d897eaec6343bd6255f8dcd349101b841a22b308f750cc54f70abbe43c53310e9c774d652ee79ef1f08ec0ae44d2204331bbb8944e223f0f79455dfa52dcf4af24ae16e333db6c859728253fb2dcb7e9401a063746963616c2062797a616e74696e65206661756c7420746f6c6572616e636588000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000", + "trustedHeight": 33, + "accountProof": "0x" + }, + "membership": { + "proof": "0xf90159f90111a02e5a83120837eb86e4961e217014c155f98adcc18a96478d4942be68d231ef1f80a04e510de4b9ef26070bc6f70273e868c69edbaf19a2517970a5dbd69902e1d434a0961d17be355042d27b605ef5f08628781620f7925927a3fb4beab2c3f6ce960aa0c8f60c0b856b9c536a919218ed7620e4f347b78938a758dfbb7e51cf2987edd0a0121c2d3eac0ec9178354c8715a2c353722e19f48e88691c2212e92d9cfb289d480a0f383029e86bd678ed67013dba1678e499669b01ce6670f925b415326d2b0243fa00e8d54ce26b8005c92ece298e21e9c7d1225e884addcdfbea2ead81c551df8928080808080a028d7dc5ba83020579a12100e30fafb74f3c03531f786808a733392cd565ef0668080f843a0369632698e78112a478dabed541f773d2f5a93186d9d3b9d9774b73bf9018b08a1a0d7d01afac573bfdecea02b26ffc115aab06e9b364869695b5e22775c252ba5e6", + "proofHeight": 35, + "path": "0x626573752d636861696e2d62010000000000000001", + "value": "0xd7d01afac573bfdecea02b26ffc115aab06e9b364869695b5e22775c252ba5e6", + "expectedTimestamp": 1787357309 + }, + "nonMembership": { + "proof": "0xf90167f90111a02e5a83120837eb86e4961e217014c155f98adcc18a96478d4942be68d231ef1f80a04e510de4b9ef26070bc6f70273e868c69edbaf19a2517970a5dbd69902e1d434a0961d17be355042d27b605ef5f08628781620f7925927a3fb4beab2c3f6ce960aa0c8f60c0b856b9c536a919218ed7620e4f347b78938a758dfbb7e51cf2987edd0a0121c2d3eac0ec9178354c8715a2c353722e19f48e88691c2212e92d9cfb289d480a0f383029e86bd678ed67013dba1678e499669b01ce6670f925b415326d2b0243fa00e8d54ce26b8005c92ece298e21e9c7d1225e884addcdfbea2ead81c551df8928080808080a028d7dc5ba83020579a12100e30fafb74f3c03531f786808a733392cd565ef0668080f85180808080a0875eb9f9e615bfe1bd0884f44df3e2d591dd593d8009f0580aab4465dde3c0518080808080808080a02e971ba04a6d372cbe0b0622575c81175795858250053878c51e727d46591fa8808080", + "proofHeight": 35, + "path": "0x626573752d636861696e2d61020000000000000001", + "expectedTimestamp": 1787357309 + } +} diff --git a/ibc-solidity/test/solidity-ibc/IFTTest.t.sol b/ibc-solidity/test/solidity-ibc/IFTTest.t.sol index dd280c7e6..7ae7974b5 100644 --- a/ibc-solidity/test/solidity-ibc/IFTTest.t.sol +++ b/ibc-solidity/test/solidity-ibc/IFTTest.t.sol @@ -53,9 +53,8 @@ contract IFTTest is Test { function setUpOwnable() public { address impl = address(new IFTOwnable()); - ERC1967Proxy proxy = new ERC1967Proxy( - impl, abi.encodeCall(IFTOwnable.initialize, (admin, TOKEN_NAME, TOKEN_SYMBOL, mockICS27)) - ); + ERC1967Proxy proxy = + new ERC1967Proxy(impl, abi.encodeCall(IFTOwnable.initialize, (admin, TOKEN_NAME, TOKEN_SYMBOL, mockICS27))); ift = IIFT(address(proxy)); } diff --git a/packages/proof-api/modules/besu-to-eth/Cargo.toml b/packages/proof-api/modules/besu-to-eth/Cargo.toml new file mode 100644 index 000000000..674b94e83 --- /dev/null +++ b/packages/proof-api/modules/besu-to-eth/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "proof-api-besu-to-eth" +version.workspace = true +edition.workspace = true +repository.workspace = true +license.workspace = true + +[dependencies] +alloy = { workspace = true, features = ["full"] } +alloy-rlp = { workspace = true } +anyhow = { workspace = true, features = ["std"] } +ethereum-apis = { workspace = true } +ethereum-light-client = { workspace = true } +proof-api-core = { workspace = true, default-features = false } +proof-api-lib = { workspace = true, default-features = false } +ibc-eureka-solidity-types = { workspace = true, features = ["rpc"] } +rlp = { workspace = true } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true } +tonic = { workspace = true, default-features = true } +tracing = { workspace = true, default-features = true } diff --git a/packages/proof-api/modules/besu-to-eth/src/lib.rs b/packages/proof-api/modules/besu-to-eth/src/lib.rs new file mode 100644 index 000000000..c5c5882de --- /dev/null +++ b/packages/proof-api/modules/besu-to-eth/src/lib.rs @@ -0,0 +1,242 @@ +// SPDX-License-Identifier: Apache-2.0 + +//! One-sided Besu-to-Ethereum proof API module. + +#![deny(clippy::nursery, clippy::pedantic, warnings, unused_crate_dependencies)] +#![allow(missing_docs)] + +mod tx_builder; + +use std::collections::HashMap; + +use alloy::{ + primitives::{Address, TxHash}, + providers::{Provider, RootProvider}, +}; +use proof_api_core::{ + api::{self, proof_api_service_server::ProofApiService}, + modules::ProofApiModule, +}; +use proof_api_lib::{ + listener::{eth_eureka, ChainListenerService}, + service_utils::{parse_eth_tx_hashes, to_tonic_status}, + utils::RelayEventsParams, +}; +use tonic::{Request, Response}; +use tracing as _; +use tx_builder::TxBuilder; + +#[derive(Clone, Copy, Debug)] +pub struct BesuToEthProofApiModule; + +struct BesuToEthProofApiModuleService { + src_ics26_address: Address, + src_listener: eth_eureka::ChainListener, + dst_listener: eth_eureka::ChainListener, + tx_builder: TxBuilder, +} + +#[derive(Clone, Copy, Debug, serde::Deserialize, serde::Serialize)] +#[serde(rename_all = "snake_case")] +pub enum BesuConsensusType { + Qbft, + Ibft2, +} + +#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] +pub struct BesuToEthConfig { + pub src_rpc_url: String, + pub src_ics26_address: Address, + pub dst_rpc_url: String, + pub dst_ics26_address: Address, + pub consensus_type: BesuConsensusType, +} + +impl BesuToEthProofApiModuleService { + async fn new(config: BesuToEthConfig) -> anyhow::Result { + let src_provider = RootProvider::builder() + .connect(&config.src_rpc_url) + .await + .map_err(|e| anyhow::anyhow!("failed to create source provider: {e}"))?; + let dst_provider = RootProvider::builder() + .connect(&config.dst_rpc_url) + .await + .map_err(|e| anyhow::anyhow!("failed to create destination provider: {e}"))?; + + let src_listener = + eth_eureka::ChainListener::new(config.src_ics26_address, src_provider.clone()); + let dst_listener = + eth_eureka::ChainListener::new(config.dst_ics26_address, dst_provider.clone()); + let tx_builder = TxBuilder::new( + src_provider, + dst_provider, + config.src_ics26_address, + config.dst_ics26_address, + config.consensus_type, + ); + + Ok(Self { + src_ics26_address: config.src_ics26_address, + src_listener, + dst_listener, + tx_builder, + }) + } +} + +#[tonic::async_trait] +impl ProofApiService for BesuToEthProofApiModuleService { + async fn info( + &self, + request: Request, + ) -> Result, tonic::Status> { + let src_chain = request.into_inner().src_chain; + Ok(Response::new(api::InfoResponse { + target_chain: Some(api::Chain { + chain_id: self + .dst_listener + .chain_id() + .await + .map_err(to_tonic_status)?, + ibc_version: "2".to_string(), + ibc_contract: self.tx_builder.ics26_router_address().to_string(), + }), + source_chain: Some(api::Chain { + chain_id: src_chain, + ibc_version: "2".to_string(), + ibc_contract: self.src_ics26_address.to_string(), + }), + metadata: HashMap::default(), + })) + } + + async fn relay_by_tx( + &self, + request: Request, + ) -> Result, tonic::Status> { + let inner_req = request.into_inner(); + + let src_txs = parse_eth_tx_hashes(inner_req.source_tx_ids)? + .into_iter() + .map(TxHash::from) + .collect(); + let timeout_txs = parse_eth_tx_hashes(inner_req.timeout_tx_ids)? + .into_iter() + .map(TxHash::from) + .collect(); + + let src_events = self + .src_listener + .fetch_tx_events(src_txs) + .await + .map_err(to_tonic_status)?; + let timeout_events = self + .dst_listener + .fetch_tx_events(timeout_txs) + .await + .map_err(to_tonic_status)?; + + let timeout_relay_height = if timeout_events.is_empty() { + None + } else { + Some( + self.src_listener + .get_block_number() + .await + .map_err(to_tonic_status)?, + ) + }; + + let tx = self + .tx_builder + .relay_events(RelayEventsParams { + src_events, + target_events: timeout_events, + timeout_relay_height, + src_client_id: inner_req.src_client_id, + dst_client_id: inner_req.dst_client_id, + src_packet_seqs: inner_req.src_packet_sequences, + dst_packet_seqs: inner_req.dst_packet_sequences, + }) + .await + .map_err(to_tonic_status)?; + + Ok(Response::new(api::RelayByTxResponse { + tx, + address: self.tx_builder.ics26_router_address().to_string(), + })) + } + + async fn create_client( + &self, + request: Request, + ) -> Result, tonic::Status> { + let inner_req = request.into_inner(); + let tx = self + .tx_builder + .create_client(&inner_req.parameters) + .await + .map_err(to_tonic_status)?; + + Ok(Response::new(api::CreateClientResponse { + tx, + address: String::new(), + })) + } + + async fn update_client( + &self, + request: Request, + ) -> Result, tonic::Status> { + let inner_req = request.into_inner(); + let tx = self + .tx_builder + .update_client(&inner_req.dst_client_id) + .await + .map_err(to_tonic_status)?; + + Ok(Response::new(api::UpdateClientResponse { + tx, + address: self.tx_builder.ics26_router_address().to_string(), + })) + } +} + +#[tonic::async_trait] +impl ProofApiModule for BesuToEthProofApiModule { + fn name(&self) -> &'static str { + "besu_to_eth" + } + + async fn create_service( + &self, + config: serde_json::Value, + ) -> anyhow::Result> { + let config: BesuToEthConfig = serde_json::from_value(config)?; + let service = BesuToEthProofApiModuleService::new(config).await?; + Ok(Box::new(service)) + } +} + +#[cfg(test)] +mod tests { + use super::BesuToEthConfig; + + #[test] + fn obsolete_src_chain_id_is_ignored() { + let config: BesuToEthConfig = serde_json::from_value(serde_json::json!({ + "src_chain_id": "legacy", + "src_rpc_url": "http://localhost:8545", + "src_ics26_address": "0x0000000000000000000000000000000000000001", + "dst_rpc_url": "http://localhost:9545", + "dst_ics26_address": "0x0000000000000000000000000000000000000002", + "consensus_type": "qbft" + })) + .unwrap(); + + assert!( + serde_json::to_value(config).unwrap()["src_chain_id"].is_null(), + "obsolete field must be accepted but not emitted" + ); + } +} diff --git a/packages/proof-api/modules/besu-to-eth/src/tx_builder.rs b/packages/proof-api/modules/besu-to-eth/src/tx_builder.rs new file mode 100644 index 000000000..e100bb891 --- /dev/null +++ b/packages/proof-api/modules/besu-to-eth/src/tx_builder.rs @@ -0,0 +1,613 @@ +// SPDX-License-Identifier: Apache-2.0 + +use std::{ + collections::{HashMap, HashSet}, + str::FromStr, + time::UNIX_EPOCH, +}; + +use alloy::{ + consensus::Header, + network::Ethereum, + primitives::{hex, Address, Bytes, B256, U256}, + providers::{Provider, RootProvider}, + rpc::types::{EIP1186AccountProofResponse, EIP1186StorageProof}, + sol_types::{SolCall, SolValue}, +}; +use alloy_rlp::Header as RlpHeader; +use anyhow::{anyhow, bail, Context, Result}; +use ethereum_apis::eth_api::client::EthApiClient; +use ethereum_light_client::membership::evm_ics26_commitment_path; +use ibc_eureka_solidity_types::{ + besu::{besu_ibft2_light_client, besu_qbft_light_client}, + ics26::{ + router::{multicallCall, routerCalls, routerInstance, updateClientCall}, + IICS02ClientMsgs::Height as RouterHeight, + ICS26_IBC_STORAGE_SLOT, + }, + msgs::{IBesuLightClientMsgs, IICS02ClientMsgs::Height as MsgHeight}, +}; +use proof_api_lib::utils::{ + eth_eureka::{src_events_to_recv_and_ack_msgs, target_events_to_timeout_msgs}, + RelayEventsParams, +}; +use rlp::Rlp; + +use crate::BesuConsensusType; + +pub struct TxBuilder { + src_provider: RootProvider, + dst_provider: RootProvider, + src_ics26_router: routerInstance, + dst_ics26_router: routerInstance, + consensus_type: BesuConsensusType, +} + +struct CreateClientParams { + trusting_period: u64, + max_clock_drift: u64, + trusted_height: Option, + role_manager: Address, +} + +const TRUSTING_PERIOD: &str = "trusting_period"; +const MAX_CLOCK_DRIFT: &str = "max_clock_drift"; +const TRUSTED_HEIGHT: &str = "trusted_height"; +const ROLE_MANAGER: &str = "role_manager"; + +impl TxBuilder { + pub fn new( + src_provider: RootProvider, + dst_provider: RootProvider, + src_ics26_address: Address, + dst_ics26_address: Address, + consensus_type: BesuConsensusType, + ) -> Self { + Self { + src_ics26_router: routerInstance::new(src_ics26_address, src_provider.clone()), + dst_ics26_router: routerInstance::new(dst_ics26_address, dst_provider.clone()), + src_provider, + dst_provider, + consensus_type, + } + } + + pub const fn ics26_router_address(&self) -> &Address { + self.dst_ics26_router.address() + } + + pub async fn create_client(&self, parameters: &HashMap) -> Result> { + let params = parse_create_client_params(parameters)?; + let trusted_height = match params.trusted_height { + Some(height) => height, + None => self + .src_provider + .get_block_number() + .await + .context("failed to fetch latest source block number")?, + }; + + let header = self + .fetch_source_header(trusted_height) + .await + .with_context(|| format!("failed to fetch source block at height {trusted_height}"))?; + let validators = + extract_validators_from_extra_data(&header.extra_data).with_context(|| { + format!("failed to extract validators from source block {trusted_height}") + })?; + let proof = self + .fetch_source_proofs(trusted_height, &[]) + .await + .with_context(|| { + format!( + "failed to fetch account proof for source router at height {trusted_height}" + ) + })?; + + let calldata = match self.consensus_type { + BesuConsensusType::Qbft => besu_qbft_light_client::BesuQBFTLightClient::deploy_builder( + self.dst_provider.clone(), + *self.src_ics26_router.address(), + trusted_height, + header.timestamp, + proof.storage_hash, + validators, + params.trusting_period, + params.max_clock_drift, + params.role_manager, + ) + .calldata() + .to_vec(), + BesuConsensusType::Ibft2 => { + besu_ibft2_light_client::BesuIBFT2LightClient::deploy_builder( + self.dst_provider.clone(), + *self.src_ics26_router.address(), + trusted_height, + header.timestamp, + proof.storage_hash, + validators, + params.trusting_period, + params.max_clock_drift, + params.role_manager, + ) + .calldata() + .to_vec() + } + }; + + Ok(calldata) + } + + pub async fn update_client(&self, dst_client_id: &str) -> Result> { + let client_state = self + .fetch_destination_client_state(dst_client_id) + .await + .with_context(|| { + format!("failed to decode destination Besu client state for client {dst_client_id}") + })?; + let trusted_height = client_state.latestHeight.revisionHeight; + let target_height = self + .src_provider + .get_block_number() + .await + .context("failed to fetch latest source block number")?; + let header = self + .fetch_source_header(target_height) + .await + .with_context(|| format!("failed to fetch source block at height {target_height}"))?; + let proof = self + .fetch_source_proofs(target_height, &[]) + .await + .with_context(|| { + format!("failed to fetch account proof for source router at height {target_height}") + })?; + + Ok(Self::build_update_client_calldata( + dst_client_id, + trusted_height, + header, + encode_rlp_node_list(&proof.account_proof), + )) + } + + pub async fn relay_events(&self, params: RelayEventsParams) -> Result> { + let proof_height = params + .src_events + .iter() + .map(|event| event.height) + .chain(params.timeout_relay_height) + .max() + .ok_or_else(|| anyhow!("no packets collected"))?; + let header = self + .fetch_source_header(proof_height) + .await + .with_context(|| format!("failed to fetch source block at height {proof_height}"))?; + let proof_timestamp = header.timestamp; + let now = std::time::SystemTime::now() + .duration_since(UNIX_EPOCH) + .context("failed to read system time")? + .as_secs(); + let proof_height_msg = RouterHeight { + revisionNumber: 0, + revisionHeight: proof_height, + }; + + let recv_and_ack_msgs = src_events_to_recv_and_ack_msgs( + params.src_events, + ¶ms.src_client_id, + ¶ms.dst_client_id, + ¶ms.src_packet_seqs, + ¶ms.dst_packet_seqs, + &proof_height_msg, + now, + )?; + let timeout_msgs = target_events_to_timeout_msgs( + params.target_events, + ¶ms.src_client_id, + ¶ms.dst_client_id, + ¶ms.dst_packet_seqs, + &proof_height_msg, + proof_timestamp, + ); + + let mut packet_calls: Vec<_> = recv_and_ack_msgs.into_iter().chain(timeout_msgs).collect(); + if packet_calls.is_empty() { + bail!("no packets collected") + } + + let client_state = self + .fetch_destination_client_state(¶ms.dst_client_id) + .await + .with_context(|| { + format!( + "failed to decode destination Besu client state for client {}", + params.dst_client_id + ) + })?; + let mut storage_keys = packet_calls + .iter() + .map(packet_storage_key) + .collect::>(); + storage_keys.sort_unstable(); + storage_keys.dedup(); + let proof = self + .fetch_source_proofs(proof_height, &storage_keys) + .await + .with_context(|| { + format!( + "failed to fetch account and storage proofs for source router at height {proof_height}" + ) + })?; + let account_proof = encode_rlp_node_list(&proof.account_proof); + let storage_proofs = map_storage_proofs(&storage_keys, proof.storage_proof)?; + let update_call = Self::build_update_client_calldata( + ¶ms.dst_client_id, + client_state.latestHeight.revisionHeight, + header, + account_proof, + ); + + attach_packet_proofs(&mut packet_calls, &storage_proofs)?; + + let all_calls: Vec = std::iter::once(update_call.into()) + .chain(packet_calls.into_iter().map(|call| match call { + routerCalls::ackPacket(call) => call.abi_encode().into(), + routerCalls::recvPacket(call) => call.abi_encode().into(), + routerCalls::timeoutPacket(call) => call.abi_encode().into(), + _ => unreachable!("only recv, ack, and timeout calls are constructed"), + })) + .collect(); + + Ok(multicallCall { data: all_calls }.abi_encode()) + } + + fn build_update_client_calldata( + dst_client_id: &str, + trusted_height: u64, + header: Header, + account_proof: Vec, + ) -> Vec { + let update_msg = IBesuLightClientMsgs::MsgUpdateClient { + headerRlp: alloy_rlp::encode(header).into(), + trustedHeight: MsgHeight { + revisionNumber: 0, + revisionHeight: trusted_height, + }, + accountProof: account_proof.into(), + }; + + updateClientCall { + clientId: dst_client_id.to_string(), + updateMsg: update_msg.abi_encode().into(), + } + .abi_encode() + } + + async fn fetch_source_header(&self, block_height: u64) -> Result
{ + let block = EthApiClient::new(self.src_provider.clone()) + .get_block(block_height) + .await + .with_context(|| format!("failed to fetch source block at height {block_height}"))?; + Ok(block.into_consensus_header()) + } + + async fn fetch_source_proofs( + &self, + block_height: u64, + storage_keys: &[B256], + ) -> Result { + Ok(EthApiClient::new(self.src_provider.clone()) + .get_proof( + &self.src_ics26_router.address().to_string(), + storage_keys + .iter() + .map(|key| format!("0x{}", hex::encode(key))) + .collect(), + format!("0x{block_height:x}"), + ) + .await?) + } + + async fn fetch_destination_client_state( + &self, + dst_client_id: &str, + ) -> Result { + let client_address = self + .dst_ics26_router + .getClient(dst_client_id.to_string()) + .call() + .await + .with_context(|| { + format!("failed to fetch destination client address for {dst_client_id}") + })?; + let client_state_bz: Bytes = besu_qbft_light_client::BesuQBFTLightClient::new( + client_address, + self.dst_provider.clone(), + ) + .getClientState() + .call() + .await + .with_context(|| format!("failed to fetch destination client state for {dst_client_id}"))?; + + IBesuLightClientMsgs::ClientState::abi_decode(client_state_bz.as_ref()).with_context(|| { + format!("failed to decode destination client state for {dst_client_id}") + }) + } +} + +fn packet_storage_key(call: &routerCalls) -> B256 { + let path = match call { + routerCalls::recvPacket(call) => call.msg_.packet.commitment_path(), + routerCalls::ackPacket(call) => call.msg_.packet.ack_commitment_path(), + routerCalls::timeoutPacket(call) => call.msg_.packet.receipt_commitment_path(), + _ => unreachable!("only recv, ack, and timeout calls are constructed"), + }; + evm_ics26_commitment_path(&path, U256::from_be_slice(&ICS26_IBC_STORAGE_SLOT)).into() +} + +fn attach_packet_proofs( + packet_calls: &mut [routerCalls], + storage_proofs: &HashMap>, +) -> Result<()> { + for call in packet_calls { + let storage_key = packet_storage_key(call); + let proof: Bytes = storage_proofs + .get(&storage_key) + .ok_or_else(|| anyhow!("missing storage proof for key {storage_key}"))? + .clone() + .into(); + match call { + routerCalls::recvPacket(call) => call.msg_.proofCommitment = proof, + routerCalls::ackPacket(call) => call.msg_.proofAcked = proof, + routerCalls::timeoutPacket(call) => call.msg_.proofTimeout = proof, + _ => unreachable!("only recv, ack, and timeout calls are constructed"), + } + } + Ok(()) +} + +fn map_storage_proofs( + expected_keys: &[B256], + storage_proofs: Vec, +) -> Result>> { + let expected_keys = expected_keys.iter().copied().collect::>(); + let mut proofs = HashMap::with_capacity(expected_keys.len()); + + for storage_proof in storage_proofs { + let key = storage_proof.key.as_b256(); + if !expected_keys.contains(&key) { + bail!("unexpected storage proof key {key}"); + } + if proofs + .insert(key, encode_rlp_node_list(&storage_proof.proof)) + .is_some() + { + bail!("duplicate storage proof key {key}"); + } + } + + if let Some(key) = expected_keys.iter().find(|key| !proofs.contains_key(*key)) { + bail!("missing storage proof for key {key}"); + } + Ok(proofs) +} + +fn parse_create_client_params(parameters: &HashMap) -> Result { + parameters + .keys() + .find(|key| { + ![TRUSTING_PERIOD, MAX_CLOCK_DRIFT, TRUSTED_HEIGHT, ROLE_MANAGER] + .contains(&key.as_str()) + }) + .map_or(Ok(()), |key| { + Err(anyhow!( + "unexpected parameter `{key}`, only `{TRUSTING_PERIOD}`, `{MAX_CLOCK_DRIFT}`, `{TRUSTED_HEIGHT}`, and `{ROLE_MANAGER}` are allowed" + )) + })?; + + Ok(CreateClientParams { + trusting_period: parameters + .get(TRUSTING_PERIOD) + .ok_or_else(|| anyhow!("missing `{TRUSTING_PERIOD}` parameter"))? + .parse() + .with_context(|| format!("failed to parse `{TRUSTING_PERIOD}` as decimal seconds"))?, + max_clock_drift: parameters + .get(MAX_CLOCK_DRIFT) + .ok_or_else(|| anyhow!("missing `{MAX_CLOCK_DRIFT}` parameter"))? + .parse() + .with_context(|| format!("failed to parse `{MAX_CLOCK_DRIFT}` as decimal seconds"))?, + trusted_height: parameters + .get(TRUSTED_HEIGHT) + .map(|value| { + value.parse().with_context(|| { + format!("failed to parse `{TRUSTED_HEIGHT}` as decimal block height") + }) + }) + .transpose()?, + role_manager: parameters + .get(ROLE_MANAGER) + .map_or(Ok(Address::ZERO), |value| { + Address::from_str(value) + .with_context(|| format!("failed to parse `{ROLE_MANAGER}` as hex address")) + })?, + }) +} + +fn encode_rlp_node_list(nodes: &[Bytes]) -> Vec { + let payload_length = nodes.iter().map(|node| node.len()).sum(); + let mut encoded = Vec::new(); + RlpHeader { + list: true, + payload_length, + } + .encode(&mut encoded); + for node in nodes { + encoded.extend_from_slice(node.as_ref()); + } + encoded +} + +fn extract_validators_from_extra_data(extra_data: &[u8]) -> Result> { + let extra_data = Rlp::new(extra_data); + let validators = extra_data + .at(1) + .context("failed to read validator list from extraData")?; + + let mut out = Vec::with_capacity( + validators + .item_count() + .context("failed to read validator count")?, + ); + for validator in &validators { + let validator = validator + .data() + .context("failed to decode validator address")?; + if validator.len() != 20 { + bail!("invalid validator address length: {}", validator.len()); + } + out.push(Address::from_slice(validator)); + } + Ok(out) +} + +#[cfg(test)] +mod tests { + use super::{encode_rlp_node_list, extract_validators_from_extra_data, map_storage_proofs}; + use alloy::{ + consensus::Header, + primitives::{hex, Address, Bytes, B256, U256}, + rpc::types::EIP1186StorageProof, + }; + use alloy_rlp::Decodable; + use serde::Deserialize; + use std::str::FromStr; + + #[derive(Debug, Deserialize)] + #[serde(rename_all = "camelCase")] + struct Fixture { + non_adjacent_update: UpdateFixture, + membership: ProofFixture, + non_membership: ProofFixture, + } + + #[derive(Debug, Deserialize)] + #[serde(rename_all = "camelCase")] + struct UpdateFixture { + header_rlp: String, + account_proof: String, + expected_validators: Vec, + } + + #[derive(Debug, Deserialize)] + #[serde(rename_all = "camelCase")] + struct ProofFixture { + proof: String, + } + + fn load_fixture() -> Fixture { + serde_json::from_str(include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/../../../../ibc-solidity/test/besu-bft/fixtures/qbft.json" + ))) + .unwrap() + } + + fn decode_hex_bytes(hex_value: &str) -> Vec { + hex::decode(hex_value.trim_start_matches("0x")).unwrap() + } + + fn decode_proof_nodes(proof_rlp: &[u8]) -> Vec { + let proof = rlp::Rlp::new(proof_rlp); + proof + .iter() + .map(|node| Bytes::copy_from_slice(node.as_raw())) + .collect() + } + + #[test] + fn extracts_validators_from_fixture_header() { + let fixture = load_fixture(); + let header_rlp = decode_hex_bytes(&fixture.non_adjacent_update.header_rlp); + let header = Header::decode(&mut header_rlp.as_slice()).unwrap(); + let validators = extract_validators_from_extra_data(&header.extra_data).unwrap(); + let expected = fixture + .non_adjacent_update + .expected_validators + .iter() + .map(|address| Address::from_str(address).unwrap()) + .collect::>(); + + assert_eq!(validators, expected); + } + + #[test] + fn packs_account_proof_nodes_without_reencoding_nodes() { + let fixture = load_fixture(); + let account_proof_rlp = decode_hex_bytes(&fixture.non_adjacent_update.account_proof); + let nodes = decode_proof_nodes(&account_proof_rlp); + + assert_eq!(encode_rlp_node_list(&nodes), account_proof_rlp); + } + + #[test] + fn packs_membership_and_non_membership_storage_proofs() { + let fixture = load_fixture(); + let membership_proof = decode_hex_bytes(&fixture.membership.proof); + let non_membership_proof = decode_hex_bytes(&fixture.non_membership.proof); + + let membership_nodes = decode_proof_nodes(&membership_proof); + let non_membership_nodes = decode_proof_nodes(&non_membership_proof); + + assert_eq!(encode_rlp_node_list(&membership_nodes), membership_proof); + assert_eq!( + encode_rlp_node_list(&non_membership_nodes), + non_membership_proof + ); + } + + #[test] + fn maps_storage_proofs_by_normalized_key_and_validates_the_response() { + let first = B256::from(U256::from(1)); + let second = B256::from(U256::from(2)); + let make_proof = |key, marker| EIP1186StorageProof { + key, + value: U256::ZERO, + proof: vec![Bytes::from(vec![marker])], + }; + + let mapped = map_storage_proofs( + &[first, second, first], + vec![ + make_proof(second.into(), 2), + make_proof(U256::from(1).into(), 1), + ], + ) + .unwrap(); + assert_eq!( + mapped[&first], + encode_rlp_node_list(&[Bytes::from(vec![1])]) + ); + assert_eq!( + mapped[&second], + encode_rlp_node_list(&[Bytes::from(vec![2])]) + ); + + assert!(map_storage_proofs(&[first], vec![]) + .unwrap_err() + .to_string() + .contains("missing storage proof")); + assert!(map_storage_proofs( + &[first], + vec![make_proof(first.into(), 1), make_proof(first.into(), 1)] + ) + .unwrap_err() + .to_string() + .contains("duplicate storage proof")); + assert!( + map_storage_proofs(&[first], vec![make_proof(second.into(), 2)]) + .unwrap_err() + .to_string() + .contains("unexpected storage proof") + ); + } +} diff --git a/packages/solidity/src/besu.rs b/packages/solidity/src/besu.rs new file mode 100644 index 000000000..576a72701 --- /dev/null +++ b/packages/solidity/src/besu.rs @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: Apache-2.0 + +pub mod besu_ibft2_light_client { + #[cfg(feature = "rpc")] + alloy_sol_types::sol!( + #[sol(rpc)] + #[allow(clippy::nursery, clippy::too_many_arguments)] + BesuIBFT2LightClient, + "../../ibc-solidity/abi/bytecode/BesuIBFT2LightClient.json" + ); + + #[cfg(not(feature = "rpc"))] + alloy_sol_types::sol!( + BesuIBFT2LightClient, + "../../ibc-solidity/abi/BesuIBFT2LightClient.json" + ); +} + +pub mod besu_qbft_light_client { + #[cfg(feature = "rpc")] + alloy_sol_types::sol!( + #[sol(rpc)] + #[allow(clippy::nursery, clippy::too_many_arguments)] + BesuQBFTLightClient, + "../../ibc-solidity/abi/bytecode/BesuQBFTLightClient.json" + ); + + #[cfg(not(feature = "rpc"))] + alloy_sol_types::sol!( + BesuQBFTLightClient, + "../../ibc-solidity/abi/BesuQBFTLightClient.json" + ); +} diff --git a/packages/solidity/src/lib.rs b/packages/solidity/src/lib.rs index 18f1cbcb8..aea6d3f49 100644 --- a/packages/solidity/src/lib.rs +++ b/packages/solidity/src/lib.rs @@ -5,6 +5,7 @@ #![deny(clippy::nursery, clippy::pedantic, warnings, unused_crate_dependencies)] pub mod attestation; +pub mod besu; pub mod ics26; pub mod msgs; pub mod sp1_ics07; diff --git a/packages/solidity/src/msgs.rs b/packages/solidity/src/msgs.rs index c0a867d2c..c775ce6f5 100644 --- a/packages/solidity/src/msgs.rs +++ b/packages/solidity/src/msgs.rs @@ -45,6 +45,9 @@ alloy_sol_types::sol!( alloy_sol_types::sol!( "../../ibc-solidity/contracts/light-clients/attestation/msgs/IAttestationLightClientMsgs.sol" ); +alloy_sol_types::sol!( + "../../ibc-solidity/contracts/light-clients/besu/msgs/IBesuLightClientMsgs.sol" +); #[cfg(feature = "rpc")] impl ISP1Msgs::SP1Proof { diff --git a/programs/proof-api/Cargo.toml b/programs/proof-api/Cargo.toml index 70427d9ff..4263d9d31 100644 --- a/programs/proof-api/Cargo.toml +++ b/programs/proof-api/Cargo.toml @@ -11,6 +11,7 @@ proof-api-eth-to-cosmos = { workspace = true, default-features = false } proof-api-eth-to-cosmos-compat = { workspace = true, default-features = false } proof-api-cosmos-to-eth = { workspace = true, default-features = false } proof-api-eth-to-eth = { workspace = true, default-features = false } +proof-api-besu-to-eth = { workspace = true, default-features = false } proof-api-cosmos-to-cosmos = { workspace = true, default-features = false } proof-api-solana-to-cosmos = { workspace = true, default-features = false } proof-api-cosmos-to-solana = { workspace = true, default-features = false } diff --git a/programs/proof-api/README.md b/programs/proof-api/README.md index 9bced7883..81072bccd 100644 --- a/programs/proof-api/README.md +++ b/programs/proof-api/README.md @@ -23,6 +23,7 @@ Each module runs in one direction and specializes in how it builds proofs and tr | `cosmos_to_eth` | Cosmos SDK | EVM | Parse Cosmos events, build EVM IBC txs | `sp1` — ZK proofs via SP1
`attested` — multisig attestations | | `eth_to_cosmos` | EVM | Cosmos SDK | Parse EVM events, build Cosmos IBC txs | `real` — ethereum mainnet beacon API proofs
`mock` — dev/test mode
`attested` — multisig attestations | | `eth_to_eth` | EVM | EVM | Parse EVM events, build attested txs | `attested` — multisig attestations | +| `besu_to_eth` | Besu BFT EVM | EVM | Parse EVM events, build EVM real-proof txs | direct Besu light-client updates + Besu account/storage proofs | | `cosmos_to_cosmos` | Cosmos SDK | Cosmos SDK | Parse Cosmos events, build Cosmos IBC txs | ICS-07 light client proofs only (validator signatures and merkle proofs) | | `cosmos_to_solana` | Cosmos SDK | Solana | Parse Cosmos events, build Solana IBC txs | ICS-07 light client proofs only (validator signatures and merkle proofs) | | `solana_to_cosmos` | Solana | Cosmos SDK | Parse Solana events, build Cosmos IBC txs | multisig attestations only | @@ -62,7 +63,7 @@ Key settings: - `observability.use_otel`: Enable OpenTelemetry export. - `observability.service_name`: Service name used in logs/traces. - `observability.otel_endpoint`: OpenTelemetry collector endpoint. -- `modules`: List of modules to run, each with `name`, `src_chain`, `dst_chain`, `config`, and optional `enabled` (defaults to true). For `eth_to_eth`, `Info` returns the routed `src_chain` as the source identity and the destination RPC chain ID as the target identity. +- `modules`: List of modules to run, each with `name`, `src_chain`, `dst_chain`, `config`, and optional `enabled` (defaults to true). For EVM-to-EVM modules, `Info` returns the routed `src_chain` as the source identity and the destination RPC chain ID as the target identity. Module configuration varies by module type. Mode-specific options are enumerated below. @@ -124,6 +125,12 @@ Module configuration varies by module type: - `mode.cache`: Optional cache config. - `mode.cache.state_cache_max_entries`. (default: 10000) - `mode.cache.packet_cache_max_entries`. (default: 10000) +- `besu_to_eth`: + - `src_rpc_url`: Source Besu RPC endpoint. + - `src_ics26_address`: Source IBC router contract address. + - `dst_rpc_url`: Destination EVM RPC endpoint. + - `dst_ics26_address`: Destination IBC router contract address. + - `consensus_type`: Source Besu consensus type, `qbft` or `ibft2`. - `cosmos_to_cosmos`: - `src_rpc_url`: RPC endpoint for the source chain. - `target_rpc_url`: RPC endpoint for the destination chain. @@ -142,6 +149,23 @@ Module configuration varies by module type: - `signer_address`: Cosmos address used for message construction metadata. - `solana_ics26_program_id`: Solana ICS26 router program ID. +## `besu_to_eth` create-client parameters + +`besu_to_eth` `CreateClient` returns only deployment calldata for `BesuQBFTLightClient` or `BesuIBFT2LightClient`. It does not call `ICS26Router.addClient(...)`. + +Required parameters: +- `trusting_period`: Decimal seconds for the weak-subjectivity window. +- `max_clock_drift`: Decimal seconds for allowed future header drift. + +Optional parameters: +- `trusted_height`: Decimal source block height. Defaults to the latest source block. +- `role_manager`: Hex address. Defaults to the zero address. + +Operational notes: +- `consensus_type` is fixed by module config and only affects `CreateClient` wrapper selection. +- `UpdateClient` is a single direct Besu update. No catch-up or intermediate-header search is performed. +- `RelayByTx` uses real Besu proofs: full header RLP, one account proof in the client update, and storage proofs for recv/ack/timeout packet verification. + ## Using the gRPC API After the service is running, use the gRPC endpoints defined in [`proto/proofapi/proofapi.proto`](../../proto/proofapi/proofapi.proto) to submit transaction hashes and retrieve the unsigned IBC transactions plus proofs. Typical usage is: diff --git a/programs/proof-api/config.example.json b/programs/proof-api/config.example.json index effcb2fc4..883a02bf9 100644 --- a/programs/proof-api/config.example.json +++ b/programs/proof-api/config.example.json @@ -146,6 +146,19 @@ "mode": "real" } }, + { + "name": "besu_to_eth", + "src_chain": "besu-a", + "dst_chain": "besu-b", + "enabled": false, + "config": { + "src_rpc_url": "http://127.0.0.1:8545", + "src_ics26_address": "0x4242424242424242424242424242424242424242", + "dst_rpc_url": "http://127.0.0.1:9545", + "dst_ics26_address": "0x4242424242424242424242424242424242424242", + "consensus_type": "qbft" + } + }, { "name": "cosmos_to_cosmos", "src_chain": "cosmoshub-4", diff --git a/programs/proof-api/src/bin/proof-api.rs b/programs/proof-api/src/bin/proof-api.rs index c247603c7..d9c151efe 100644 --- a/programs/proof-api/src/bin/proof-api.rs +++ b/programs/proof-api/src/bin/proof-api.rs @@ -5,6 +5,7 @@ use std::{net::SocketAddr, path::PathBuf}; use clap::Parser; use proof_api::cli::{Commands, ProofApiCli}; use proof_api::observability::init_observability; +use proof_api_besu_to_eth::BesuToEthProofApiModule; use proof_api_core::{builder::ProofApiBuilder, config::ProofApiConfig}; use proof_api_cosmos_to_cosmos::CosmosToCosmosProofApiModule; use proof_api_cosmos_to_eth::CosmosToEthProofApiModule; @@ -47,6 +48,7 @@ async fn main() -> anyhow::Result<()> { proof_api_builder.add_module(EthToCosmosProofApiModule); proof_api_builder.add_module(EthToCosmosCompatProofApiModule); proof_api_builder.add_module(EthToEthProofApiModule); + proof_api_builder.add_module(BesuToEthProofApiModule); proof_api_builder.add_module(SolanaToCosmosProofApiModule); proof_api_builder.add_module(CosmosToSolanaProofApiModule); proof_api_builder.add_module(EthToSolanaProofApiModule);