diff --git a/.claude/skills/release/SKILL.md b/.claude/skills/release/SKILL.md index 7221bc0..76bb3b0 100644 --- a/.claude/skills/release/SKILL.md +++ b/.claude/skills/release/SKILL.md @@ -1,11 +1,11 @@ --- name: release -description: Cut a release of genlayer-py. Bumps version, updates CHANGELOG, tags, pushes — CI then publishes to PyPI and creates the GitHub Release. Use when a human asks "release v0.18.x" or "ship a new version". +description: Cut a release or release candidate of genlayer-py. Bumps version, updates CHANGELOG, tags, pushes — CI then publishes to PyPI and creates the GitHub Release. --- # Release skill — genlayer-py -This repo follows a branch-per-major release model. There is no auto-bump on push. A release happens when a human (or you on their behalf) runs `scripts/release.sh` on the target stable branch. +This repo follows a branch-per-release-line model. There is no auto-bump on push. A final release is cut from its stable branch; an RC is cut from the matching `*-dev` integration branch. ## When to use this skill @@ -18,12 +18,13 @@ If they ask "publish to PyPI directly" — refuse and point at this flow. The re ## What this repo's release model expects -- Branches are named after the major they ship: `v0.18` (current stable). When `v0.19` opens, the previous `v0.18` stays read-only for back-ports. +- Branches are named after the release line they ship: `v0.18` (stable) and `v0.19-dev` (integration). When `v0.19` becomes stable, the previous `v0.18` stays available for back-ports. - Tags live within those branches: `v0.18.1`, `v0.18.2`, ... - **Semver-zero rule**: this package is still on a 0.x line, so the MINOR component is the breaking-change boundary. `0.18 → 0.19` IS a major bump. `scripts/release.sh` refuses both `minor` and `major` keywords without `--allow-major` while we're on 0.x. - A major (= minor on 0.x) bump means cutting a new branch (`v0.19`) — not tagging on top of the current one. -- `CHANGELOG.md` is updated in the release commit (python-semantic-release with explicit version). -- `publish.yml` fires on the tag push and does the PyPI publish + GitHub Release. +- `CHANGELOG.md` is updated in the release commit by python-semantic-release; an explicit requested version must match the version computed from release history and conventional commits. +- Final tags are cut from `vX.Y`; RC tags such as `v0.19.0-rc.1` are cut from `vX.Y-dev`. +- `publish.yml` verifies that the tag is the current owning branch head, publishes to PyPI, and marks RC GitHub Releases as prereleases. ## Steps @@ -31,13 +32,15 @@ If they ask "publish to PyPI directly" — refuse and point at this flow. The re - Which version? If unspecified, ask whether it's patch or explicit. - If they say "minor" or "major" while we're on 0.x, surface that this means cutting a new branch — confirm before proceeding. -2. **Switch to the target branch + sync.** +2. **Switch to the owning branch + sync.** ```bash git checkout v0.18 git pull --ff-only origin v0.18 ``` If the working tree isn't clean, stop and surface what's there. + For `v0.19.0-rc.1`, use `v0.19-dev` instead. The script rejects final versions on a dev branch and prereleases on a stable branch. + 3. **Verify the head is shippable.** - Latest CI green: ```bash @@ -50,9 +53,10 @@ If they ask "publish to PyPI directly" — refuse and point at this flow. The re 4. **Run the release script.** ```bash - scripts/release.sh # or patch + scripts/release.sh # final on vX.Y + scripts/release.sh --allow-major # first RC of a new 0.x line ``` - It bumps `pyproject.toml`, updates `CHANGELOG.md`, commits `chore(release): vX.Y.Z`, tags `vX.Y.Z`, and pushes both the branch commit and the tag. It will NOT publish to PyPI — CI handles that. + First run the same command with `--dry-run`; it exercises all read-only preflight and version-policy checks. The real command bumps `pyproject.toml`, updates `CHANGELOG.md`, commits `chore(release): X.Y.Z`, tags `vX.Y.Z`, and pushes both the branch commit and the tag. It will NOT publish to PyPI — CI handles that. 5. **Watch the publish workflow.** ```bash @@ -68,8 +72,9 @@ If they ask "publish to PyPI directly" — refuse and point at this flow. The re ## Things to refuse -- **Minor or major bump on 0.x without `--allow-major`**. Those are major bumps in semver-zero and belong on a new branch. +- **Minor or major bump on 0.x without `--allow-major`**. Those are major bumps in semver-zero and belong on a new stable/dev branch pair. - **Releasing from `main`** — `main` is retired. +- **A final tag from `*-dev`, or an RC tag from the stable branch** — the tag must belong to the exact owning branch. - **Hand-editing `pyproject.toml` to bump the version** — the script keeps pyproject, the CHANGELOG entry, the commit message, and the tag in lockstep. - **Publishing a tag where `publish.yml` failed** — fix the underlying issue, re-cut the release (delete the bad tag locally and on origin, re-run the script). diff --git a/.github/scripts/validate-branch-policy.sh b/.github/scripts/validate-branch-policy.sh new file mode 100755 index 0000000..0fb7ee2 --- /dev/null +++ b/.github/scripts/validate-branch-policy.sh @@ -0,0 +1,107 @@ +#!/usr/bin/env bash +set -euo pipefail + +failed=0 + +error() { + echo "::error::$*" + failed=1 +} + +warning() { + echo "::warning::$*" +} + +active_branch_file="support/ci/ACTIVE_DEV_BRANCH" +if [[ ! -f "${active_branch_file}" ]]; then + error "${active_branch_file} is required." + active_branch="" +else + active_branch="$(tr -d '[:space:]' < "${active_branch_file}")" +fi + +if [[ -z "${active_branch}" ]]; then + error "${active_branch_file} must not be empty." +elif [[ "${active_branch}" == "main" ]]; then + error "${active_branch_file} must point to a dev branch, not main." +elif [[ "${active_branch}" != *-dev ]]; then + warning "${active_branch_file} should normally point to a -dev branch; got ${active_branch}." +fi + +release_branch="${active_branch%-dev}" +default_branch="${GITHUB_DEFAULT_BRANCH:-}" +event_name="${GITHUB_EVENT_NAME:-local}" +base_ref="${GITHUB_BASE_REF:-}" +head_ref="${GITHUB_HEAD_REF:-}" +ref_name="${GITHUB_REF_NAME:-}" +actor="${GITHUB_ACTOR:-}" + +if [[ -n "${default_branch}" && "${default_branch}" != "main" ]]; then + warning "Repository default branch should be main after branch-policy rollout; currently ${default_branch}." +fi + +if [[ -n "${base_ref}" && "${base_ref}" == "main" ]]; then + warning "PR targets main; retarget-main-prs should move it to ${active_branch}." +fi + +if [[ -n "${base_ref}" && -n "${active_branch}" ]]; then + if [[ "${base_ref}" == "${release_branch}" && "${head_ref}" != "${active_branch}" && "${ALLOW_DIRECT_RELEASE_PR:-false}" != "true" ]]; then + error "PRs into ${release_branch} must come from ${active_branch}. Merge feature work into ${active_branch}, then promote ${active_branch} -> ${release_branch}." + fi +fi + +if [[ "${event_name}" == "push" && "${ref_name}" == "main" ]]; then + case "${actor}" in + github-actions[bot]|ci-core-e2e-runner[bot]) + ;; + *) + error "main should only move by automation from ${active_branch}; direct push actor was ${actor:-unknown}." + ;; + esac +fi + +if [[ ! -f ".github/workflows/fast-forward-main.yaml" ]]; then + error ".github/workflows/fast-forward-main.yaml is required." +fi + +if [[ ! -f ".github/workflows/retarget-main-prs.yaml" ]]; then + error ".github/workflows/retarget-main-prs.yaml is required." +fi + +if [[ -f ".github/workflows/release-from-main.yml" ]]; then + error ".github/workflows/release-from-main.yml is forbidden. Releases must be tag/version-branch driven." +fi + +if [[ -f "release.config.js" ]]; then + error "release.config.js is forbidden in versioned tooling branches; semantic-release-on-main must not be restored." +fi + +if [[ -f ".github/workflows/release-from-tag.yml" ]]; then + if ! grep -Fq 'v*.*.*' .github/workflows/release-from-tag.yml; then + error "release-from-tag.yml must trigger only from version tags matching v*.*.*." + fi + if ! grep -Fq 'refs/remotes/origin/${version_branch}' .github/workflows/release-from-tag.yml || \ + ! grep -Fq 'tag_commit' .github/workflows/release-from-tag.yml || \ + ! grep -Fq 'branch_head' .github/workflows/release-from-tag.yml; then + error "release-from-tag.yml must verify the tag commit is the current matching version branch head." + fi +fi + +if [[ -f ".github/workflows/manual-docker-release.yml" ]]; then + if ! grep -Fq 'expected_branch=' .github/workflows/manual-docker-release.yml; then + error "manual-docker-release.yml must derive and enforce the expected version branch from the tag." + fi + if ! grep -Fq './.github/workflows/release-from-tag.yml' .github/workflows/manual-docker-release.yml; then + error "manual-docker-release.yml must delegate image promotion to release-from-tag.yml." + fi +fi + +if [[ "${failed}" -ne 0 ]]; then + exit 1 +fi + +if [[ -n "${base_ref}" ]]; then + echo "Branch policy ok for PR ${head_ref} -> ${base_ref}; active dev branch is ${active_branch}." +else + echo "Branch policy ok for ${event_name} on ${ref_name:-detached ref}; active dev branch is ${active_branch}." +fi diff --git a/.github/workflows/branch-policy.yml b/.github/workflows/branch-policy.yml new file mode 100644 index 0000000..7759870 --- /dev/null +++ b/.github/workflows/branch-policy.yml @@ -0,0 +1,24 @@ +name: Branch Policy + +on: + pull_request: + types: [opened, synchronize, reopened, edited, ready_for_review] + push: + branches: + - "**" + workflow_dispatch: + +permissions: + contents: read + +jobs: + branch-policy: + name: Validate branch policy + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Validate branch policy + env: + GITHUB_DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + run: ./.github/scripts/validate-branch-policy.sh diff --git a/.github/workflows/fast-forward-main.yaml b/.github/workflows/fast-forward-main.yaml new file mode 100644 index 0000000..688e997 --- /dev/null +++ b/.github/workflows/fast-forward-main.yaml @@ -0,0 +1,57 @@ +name: Fast-forward main + +# main is the static/default branch for GitHub UX and tools that assume a +# stable default branch. It is not the integration target. On each push to the +# configured active dev branch, fast-forward main to that commit. + +on: + push: + branches: ["**"] + workflow_dispatch: + +permissions: + contents: write + +concurrency: + group: fast-forward-main-${{ github.repository }} + cancel-in-progress: false + +defaults: + run: + shell: bash + +jobs: + fast-forward: + if: github.ref_type == 'branch' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Fast-forward main to active dev branch + run: | + set -euo pipefail + + active_branch="$(tr -d '[:space:]' < support/ci/ACTIVE_DEV_BRANCH)" + if [[ -z "${active_branch}" || "${active_branch}" == "main" ]]; then + echo "::error::support/ci/ACTIVE_DEV_BRANCH must name a non-main dev branch" + exit 1 + fi + + if [[ "${GITHUB_REF_NAME}" != "${active_branch}" ]]; then + echo "Push was to ${GITHUB_REF_NAME}; active dev branch is ${active_branch}. Nothing to do." + exit 0 + fi + + if git ls-remote --exit-code --heads origin main >/dev/null 2>&1; then + git fetch origin main + if ! git merge-base --is-ancestor origin/main HEAD; then + echo "::error::main has diverged from ${active_branch}; refusing non-fast-forward update" + exit 1 + fi + else + echo "main does not exist yet; creating it at ${GITHUB_SHA}." + fi + + git push origin "HEAD:refs/heads/main" diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index c33afa3..5fa301f 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,17 +1,19 @@ name: Publish Package to PyPI # Tag-driven publish. The release is cut by a human (or Claude via the -# release skill) running scripts/release.sh on the target stable branch +# release skill) running scripts/release.sh on the owning version branch # — that script bumps pyproject.toml, updates CHANGELOG.md, commits, # tags vX.Y.Z, and pushes both the branch commit and the tag. This # workflow fires on the tag push, runs tests, sanity-checks the tag # matches pyproject.toml, builds, and publishes to PyPI. It never # bumps or tags by itself. on: - workflow_dispatch: push: tags: - - "v*" + - "v*.*.*" + +permissions: + contents: write jobs: run-tests: @@ -33,16 +35,22 @@ jobs: - name: Install Python run: uv python install 3.12 - - name: Verify tag matches pyproject.toml version + - name: Verify tag, package version, and owning branch run: | TAG_VERSION="${GITHUB_REF_NAME#v}" PKG_VERSION="$(grep -E '^version = ' pyproject.toml | head -1 | sed -E 's/version = "([^"]+)"/\1/')" - if [ "$TAG_VERSION" != "$PKG_VERSION" ]; then - echo "Tag ($TAG_VERSION) and pyproject.toml ($PKG_VERSION) disagree — refusing to publish." >&2 - echo "Re-cut the release via scripts/release.sh so the tag and the committed version match." >&2 + NORMALIZED_VERSION="$(python scripts/release_version.py verify-tag "$TAG_VERSION" "$PKG_VERSION")" + EXPECTED_BRANCH="$(python scripts/release_version.py branch "$TAG_VERSION")" + git fetch --no-tags origin \ + "refs/heads/$EXPECTED_BRANCH:refs/remotes/origin/$EXPECTED_BRANCH" + TAG_COMMIT="$(git rev-parse "${GITHUB_REF_NAME}^{commit}")" + BRANCH_HEAD="$(git rev-parse "origin/$EXPECTED_BRANCH")" + if [ "$TAG_COMMIT" != "$BRANCH_HEAD" ]; then + echo "Tag $GITHUB_REF_NAME points to $TAG_COMMIT, but $EXPECTED_BRANCH is at $BRANCH_HEAD." >&2 + echo "Re-cut the release from the current owning branch head via scripts/release.sh." >&2 exit 1 fi - echo "Tag $GITHUB_REF_NAME matches pyproject.toml $PKG_VERSION." + echo "Tag $GITHUB_REF_NAME matches package $NORMALIZED_VERSION and $EXPECTED_BRANCH@$BRANCH_HEAD." - name: Clean previous builds run: rm -rf -- dist build *.egg-info @@ -63,6 +71,10 @@ jobs: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | + RELEASE_FLAGS=() + if [ "$(python scripts/release_version.py is-prerelease "$GITHUB_REF_NAME")" = "true" ]; then + RELEASE_FLAGS+=(--prerelease) + fi NOTES="$(awk -v ver="$GITHUB_REF_NAME" ' $0 ~ "^## \\[?" substr(ver, 2) {capture=1; next} capture && /^## / {exit} @@ -73,4 +85,5 @@ jobs: fi gh release create "$GITHUB_REF_NAME" \ --title "$GITHUB_REF_NAME" \ - --notes "$NOTES" + --notes "$NOTES" \ + "${RELEASE_FLAGS[@]}" diff --git a/.github/workflows/retarget-main-prs.yaml b/.github/workflows/retarget-main-prs.yaml new file mode 100644 index 0000000..37a066f --- /dev/null +++ b/.github/workflows/retarget-main-prs.yaml @@ -0,0 +1,53 @@ +name: Retarget main PRs + +# main is a static/default alias of the active dev branch. Contributions should +# target the active dev branch directly; PRs opened against main are retargeted +# automatically so required checks and release-train rules run in the right +# branch context. +# +# pull_request_target is used for the write-scoped token. This workflow never +# checks out or executes PR head code; it reads only trusted base-branch files. + +on: + pull_request_target: + types: [opened, reopened, synchronize, edited, ready_for_review] + +permissions: + contents: read + pull-requests: write + issues: write + +defaults: + run: + shell: bash + +jobs: + retarget: + if: github.event.pull_request.base.ref == 'main' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.base.ref }} + + - name: Retarget PR to active dev branch + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR_NUMBER: ${{ github.event.pull_request.number }} + run: | + set -euo pipefail + + active_branch="$(tr -d '[:space:]' < support/ci/ACTIVE_DEV_BRANCH)" + if [[ -z "${active_branch}" || "${active_branch}" == "main" ]]; then + echo "::error::support/ci/ACTIVE_DEV_BRANCH must name a non-main dev branch" + exit 1 + fi + + gh pr edit "${PR_NUMBER}" --repo "${GITHUB_REPOSITORY}" --base "${active_branch}" + + gh pr comment "${PR_NUMBER}" --repo "${GITHUB_REPOSITORY}" --body "$(cat < +## v0.19.0-rc.2 (2026-09-03) + +### Bug Fixes + +- Align localnet chain id with Studio ([#115](https://github.com/genlayerlabs/genlayer-py/pull/115), + [`4556920`](https://github.com/genlayerlabs/genlayer-py/commit/4556920d58108642131089f5ecc0a678d592a400)) + +### Build System + +- Keep release lock metadata in sync ([#115](https://github.com/genlayerlabs/genlayer-py/pull/115), + [`4556920`](https://github.com/genlayerlabs/genlayer-py/commit/4556920d58108642131089f5ecc0a678d592a400)) + + +## v0.19.0-rc.1 (2026-09-03) + +### Bug Fixes + +- Align Python SDK consumers with the resolution-kernel train + ([#109](https://github.com/genlayerlabs/genlayer-py/pull/109), + [`85a4782`](https://github.com/genlayerlabs/genlayer-py/commit/85a47821c2771b5d931b754d4a43f1bd0f057246)) + +- Align Python SDK with train contracts + ([#109](https://github.com/genlayerlabs/genlayer-py/pull/109), + [`85a4782`](https://github.com/genlayerlabs/genlayer-py/commit/85a47821c2771b5d931b754d4a43f1bd0f057246)) + +- Bump package version to v0.19 ([#95](https://github.com/genlayerlabs/genlayer-py/pull/95), + [`ec7cab9`](https://github.com/genlayerlabs/genlayer-py/commit/ec7cab9f33cd0b5e40003d1dd21a4be6fef2611d)) + +- Include execution budget floor in fee estimates + ([#89](https://github.com/genlayerlabs/genlayer-py/pull/89), + [`61dd2c0`](https://github.com/genlayerlabs/genlayer-py/commit/61dd2c0c3b4f0a83771aeb030a0361a141f51e69)) + +- Include pending transactions in default nonce lookup + ([#100](https://github.com/genlayerlabs/genlayer-py/pull/100), + [`3583471`](https://github.com/genlayerlabs/genlayer-py/commit/3583471d5c4a8c18da54850961dee541fee1e5e7)) + +- Keep studio appeals on the pre-train call shape + ([#109](https://github.com/genlayerlabs/genlayer-py/pull/109), + [`85a4782`](https://github.com/genlayerlabs/genlayer-py/commit/85a47821c2771b5d931b754d4a43f1bd0f057246)) + +- Read the consensus surfaces the resolution-kernel train exposes + ([#109](https://github.com/genlayerlabs/genlayer-py/pull/109), + [`85a4782`](https://github.com/genlayerlabs/genlayer-py/commit/85a47821c2771b5d931b754d4a43f1bd0f057246)) + +- Resolve v0.19 bug hunt regressions ([#99](https://github.com/genlayerlabs/genlayer-py/pull/99), + [`3106bc8`](https://github.com/genlayerlabs/genlayer-py/commit/3106bc87955d612b5bb43fa67e225b659b657c55)) + +- Resolve v0.19-dev bug-hunt findings ([#99](https://github.com/genlayerlabs/genlayer-py/pull/99), + [`3106bc8`](https://github.com/genlayerlabs/genlayer-py/commit/3106bc87955d612b5bb43fa67e225b659b657c55)) + +- Serialize fee payloads for studio estimates + ([#88](https://github.com/genlayerlabs/genlayer-py/pull/88), + [`5d8d1ce`](https://github.com/genlayerlabs/genlayer-py/commit/5d8d1ce5d74308dc772458a13c81bfff3ce56e1d)) + +- **appeals**: Admit unfunded rounds safely + ([#110](https://github.com/genlayerlabs/genlayer-py/pull/110), + [`b88e492`](https://github.com/genlayerlabs/genlayer-py/commit/b88e4929f31587cb3658174ed175f906c2e0fc05)) + +- **appeals**: Support Studio decision-bound lifecycle + ([#109](https://github.com/genlayerlabs/genlayer-py/pull/109), + [`85a4782`](https://github.com/genlayerlabs/genlayer-py/commit/85a47821c2771b5d931b754d4a43f1bd0f057246)) + +- **fees**: Add exact quote and appeal parity + ([#110](https://github.com/genlayerlabs/genlayer-py/pull/110), + [`b88e492`](https://github.com/genlayerlabs/genlayer-py/commit/b88e4929f31587cb3658174ed175f906c2e0fc05)) + +- **fees**: Encode internal message price caps + ([#110](https://github.com/genlayerlabs/genlayer-py/pull/110), + [`b88e492`](https://github.com/genlayerlabs/genlayer-py/commit/b88e4929f31587cb3658174ed175f906c2e0fc05)) + +- **fees**: Encode schedule-free topups + ([#110](https://github.com/genlayerlabs/genlayer-py/pull/110), + [`b88e492`](https://github.com/genlayerlabs/genlayer-py/commit/b88e4929f31587cb3658174ed175f906c2e0fc05)) + +- **fees**: Fund default consensus rotations + ([#109](https://github.com/genlayerlabs/genlayer-py/pull/109), + [`85a4782`](https://github.com/genlayerlabs/genlayer-py/commit/85a47821c2771b5d931b754d4a43f1bd0f057246)) + +- **fees**: Mirror consensus deposit quote + ([#110](https://github.com/genlayerlabs/genlayer-py/pull/110), + [`b88e492`](https://github.com/genlayerlabs/genlayer-py/commit/b88e4929f31587cb3658174ed175f906c2e0fc05)) + +- **fees**: Move wildcard callKey sentinel to keccak256(empty), deploy key = bytes32(0) + ([#93](https://github.com/genlayerlabs/genlayer-py/pull/93), + [`6bfa86a`](https://github.com/genlayerlabs/genlayer-py/commit/6bfa86a160a25d789630944e4ed05f0214fc164d)) + +- **genvm**: Give VecDB its explicit distance metric 🐛 + ([#105](https://github.com/genlayerlabs/genlayer-py/pull/105), + [`39d6a37`](https://github.com/genlayerlabs/genlayer-py/commit/39d6a37a4e6f2bac93ac3c30587a2c53f30d6d53)) + +- **studio**: Bind appeal actions to decisions + ([#110](https://github.com/genlayerlabs/genlayer-py/pull/110), + [`b88e492`](https://github.com/genlayerlabs/genlayer-py/commit/b88e4929f31587cb3658174ed175f906c2e0fc05)) + +- **studio**: Decouple native appeal and lifecycle reads + ([#109](https://github.com/genlayerlabs/genlayer-py/pull/109), + [`85a4782`](https://github.com/genlayerlabs/genlayer-py/commit/85a47821c2771b5d931b754d4a43f1bd0f057246)) + +- **studio**: Surface mined envelope reverts + ([#110](https://github.com/genlayerlabs/genlayer-py/pull/110), + [`b88e492`](https://github.com/genlayerlabs/genlayer-py/commit/b88e4929f31587cb3658174ed175f906c2e0fc05)) + +### Chores + +- **genvm**: Update runner hashes and align v0.3 ABI names ⬆️ + ([#105](https://github.com/genlayerlabs/genlayer-py/pull/105), + [`39d6a37`](https://github.com/genlayerlabs/genlayer-py/commit/39d6a37a4e6f2bac93ac3c30587a2c53f30d6d53)) + +- **genvm**: Update runner hashes and rename accepted to decided ⬆️ + ([#105](https://github.com/genlayerlabs/genlayer-py/pull/105), + [`39d6a37`](https://github.com/genlayerlabs/genlayer-py/commit/39d6a37a4e6f2bac93ac3c30587a2c53f30d6d53)) + +### Continuous Integration + +- Keep main forwarded to active dev branch + ([#92](https://github.com/genlayerlabs/genlayer-py/pull/92), + [`dd25ef7`](https://github.com/genlayerlabs/genlayer-py/commit/dd25ef7f43e99a14b8fe42a64e01374845ad4d2d)) + +- Run tests on pushes to dev branches ([#90](https://github.com/genlayerlabs/genlayer-py/pull/90), + [`bc04db8`](https://github.com/genlayerlabs/genlayer-py/commit/bc04db8999b86979273408511c90c9a89620ff49)) + +- Scope down release/sync-docs to dedicated GitHub Apps + ([#76](https://github.com/genlayerlabs/genlayer-py/pull/76), + [`375c1c1`](https://github.com/genlayerlabs/genlayer-py/commit/375c1c1b94929fa6536b9481cbb9e06a06970190)) + +- Skip pre-train smoke on v0.19 PRs ([#109](https://github.com/genlayerlabs/genlayer-py/pull/109), + [`85a4782`](https://github.com/genlayerlabs/genlayer-py/commit/85a47821c2771b5d931b754d4a43f1bd0f057246)) + +- **workflows**: Sync e2e-housekeeper.yml from genlayer-e2e + ([#83](https://github.com/genlayerlabs/genlayer-py/pull/83), + [`528f2a9`](https://github.com/genlayerlabs/genlayer-py/commit/528f2a99ba915bfd1633f95fc936855f59b138d1)) + +- **workflows**: Sync e2e-housekeeper.yml from genlayer-e2e + ([#81](https://github.com/genlayerlabs/genlayer-py/pull/81), + [`3d79679`](https://github.com/genlayerlabs/genlayer-py/commit/3d796797d7594669f095e173a50b2bfbf065a588)) + +- **workflows**: Sync e2e.yml from genlayer-e2e + ([#82](https://github.com/genlayerlabs/genlayer-py/pull/82), + [`9af83c6`](https://github.com/genlayerlabs/genlayer-py/commit/9af83c60ae952a7daa3569ea3b6c53e673498b6f)) + +- **workflows**: Sync e2e.yml from genlayer-e2e + ([#80](https://github.com/genlayerlabs/genlayer-py/pull/80), + [`1b3137a`](https://github.com/genlayerlabs/genlayer-py/commit/1b3137aeb3cd92c7496e977806e04ee6fdeaefb7)) + +### Documentation + +- Add branching guide ([#94](https://github.com/genlayerlabs/genlayer-py/pull/94), + [`ab386b4`](https://github.com/genlayerlabs/genlayer-py/commit/ab386b4139a7019639dcf4e6eae0b6830c0f52a8)) + +### Features + +- Add fee-aware transaction helpers + ([`8f35989`](https://github.com/genlayerlabs/genlayer-py/commit/8f359891377530827ce0d062b5499baffa9b54e7)) + +- Branch-per-major release model + ([`8314002`](https://github.com/genlayerlabs/genlayer-py/commit/8314002b7bd510927940527fe08f15987186a486)) + +- Branch-per-major release model ([#78](https://github.com/genlayerlabs/genlayer-py/pull/78), + [`88ad157`](https://github.com/genlayerlabs/genlayer-py/commit/88ad157c84b47b7df9602d62f009d5ad8cf8529c)) + +- Prepare v0.19 Studio preview and RC release + ([#113](https://github.com/genlayerlabs/genlayer-py/pull/113), + [`34bff46`](https://github.com/genlayerlabs/genlayer-py/commit/34bff4676be3aaa86f8821136d3aacac58cea073)) + +- **calldata**: Migrate method-call key "method" -> "" (v0.6 genvm ABI) + ([#96](https://github.com/genlayerlabs/genlayer-py/pull/96), + [`ef36623`](https://github.com/genlayerlabs/genlayer-py/commit/ef36623ac7e36fb36701449f66bb61f6518d9d2e)) + +- **fees**: Estimation correctness, wait-for-decided semantics, v0.6 parity with genlayer-js + ([#90](https://github.com/genlayerlabs/genlayer-py/pull/90), + [`bc04db8`](https://github.com/genlayerlabs/genlayer-py/commit/bc04db8999b86979273408511c90c9a89620ff49)) + +- **staking**: Support the two-step operator rotation + ([#104](https://github.com/genlayerlabs/genlayer-py/pull/104), + [`2a689c0`](https://github.com/genlayerlabs/genlayer-py/commit/2a689c0465e8267a5e79641dd754850175d55c6e)) + +- **transactions**: Layer consumer and protocol lifecycles + ([#109](https://github.com/genlayerlabs/genlayer-py/pull/109), + [`85a4782`](https://github.com/genlayerlabs/genlayer-py/commit/85a47821c2771b5d931b754d4a43f1bd0f057246)) + +- **vesting**: Add vesting staking actions + ([#97](https://github.com/genlayerlabs/genlayer-py/pull/97), + [`30c262c`](https://github.com/genlayerlabs/genlayer-py/commit/30c262c48ec5f089223c584b381101074381e397)) + +- **vesting**: Validator-leg actions (join/deposit/exit/claim, operator transfer, identity, wallet + reads) ([#97](https://github.com/genlayerlabs/genlayer-py/pull/97), + [`30c262c`](https://github.com/genlayerlabs/genlayer-py/commit/30c262c48ec5f089223c584b381101074381e397)) + +- **vesting**: Vesting staking actions + ABI + ([#97](https://github.com/genlayerlabs/genlayer-py/pull/97), + [`30c262c`](https://github.com/genlayerlabs/genlayer-py/commit/30c262c48ec5f089223c584b381101074381e397)) + +### Testing + +- Add v0.19 bug hunt regressions ([#99](https://github.com/genlayerlabs/genlayer-py/pull/99), + [`3106bc8`](https://github.com/genlayerlabs/genlayer-py/commit/3106bc87955d612b5bb43fa67e225b659b657c55)) + +- **e2e**: Migrate contract fixtures to genvm v0.3 SDK API + ([#96](https://github.com/genlayerlabs/genlayer-py/pull/96), + [`ef36623`](https://github.com/genlayerlabs/genlayer-py/commit/ef36623ac7e36fb36701449f66bb61f6518d9d2e)) + + ## v0.18.0 (2026-04-22) ### Bug Fixes diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 17b6afe..dd60ca9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -30,23 +30,15 @@ Have ideas for new features or use cases? We're eager to hear them! But first: ## Branch model -This repo uses a branch-per-major release model. There is no `main`. - -- **`v0.18`** — current stable major (semver-zero, so 0.18 IS the major; 0.19 would be a major bump that gets its own branch). PRs for bug fixes / non-breaking features target this branch. -- **`v-dev`** — when next-major (i.e. next-minor on 0.x) work is in progress, this branch is open for breaking changes. PRs introducing them target this branch, not `v0.18`. -- **Older majors** stay on the repo for back-ports and security patches. Default branch on github.com is whichever major is current stable. - -When you fork or clone, the default branch is `v0.18` today. If you have a `main` branch from a previous checkout, delete it locally: - -```sh -git checkout v0.18 -git branch -D main -git remote prune origin -``` +See [docs/BRANCHING.md](docs/BRANCHING.md) for the current release-train model. +In short: independently releasable work may target the stable branch directly; +multi-feature or cross-repo train work uses the active `*-dev` integration +branch and is promoted to the matching stable branch when ready. `main` is only +the default/static GitHub branch. ## Releases -Releases are deliberate, not automatic. `scripts/release.sh` bumps the version, updates `CHANGELOG.md`, commits, tags, and pushes; CI takes over from the tag push and publishes to PyPI. See `.claude/skills/release/SKILL.md` for the full flow. +Releases are deliberate, not automatic. `scripts/release.sh` bumps the version, updates `CHANGELOG.md`, commits, tags, and pushes; CI takes over from the tag push and publishes to PyPI. Release candidates are cut from the active `*-dev` branch (for example, `v0.19.0-rc.1` from `v0.19-dev`), while final versions are cut from the matching stable branch. See `.claude/skills/release/SKILL.md` for the full flow. **Semver-zero rule**: this package is on a 0.x line, so the MINOR component is the breaking-change boundary. `0.18 → 0.19` is a major bump and needs a new branch — the script refuses `minor`/`major` keywords without `--allow-major`. @@ -170,7 +162,7 @@ The project uses automated semantic versioning based on commit messages: | `feat!:`, `fix!:`, or `BREAKING CHANGE:` | **Major** version bump | 1.0.0 → 2.0.0 | | `docs:`, `style:`, `refactor:`, `test:`, `chore:`, `build:`, `ci:` | **No** version bump | Version stays the same | -**Important**: Never manually edit version numbers in `pyproject.toml` or other files. The release automation will handle all version updates automatically when PRs are merged to the main branch. +**Important**: Never manually edit version numbers in `pyproject.toml` or other files. Final releases are cut from the stable branch and release candidates from its matching `*-dev` branch using the release automation described above. ## Logging Configuration diff --git a/README.md b/README.md index 476569d..913e3c4 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,22 @@ To install the GenLayerPY SDK, use the following command: $ pip install genlayer-py ``` +SDK releases follow their corresponding GenLayer protocol release. This +release targets the current resolution-kernel train; use the matching older SDK +release when connecting to an older deployment. + +Use the dedicated preview preset for the release-candidate Studio deployment: + +```python +from genlayer_py import create_client +from genlayer_py.chains import studio_devnet + +client = create_client(chain=studio_devnet) +``` + +`studio_devnet` targets `https://studio-dev.genlayer.com/api` (chain ID 61997). +The existing `studionet` preset remains pinned to the stable hosted Studio. + Here’s how to initialize the client and connect to the GenLayer Simulator: ### Reading a Transaction @@ -44,21 +60,20 @@ transaction = client.get_transaction(hash=transaction_hash) ```python from genlayer_py import create_client from genlayer_py.chains import localnet -from genlayer_py.types import TransactionStatus client = create_client(chain=localnet) # Get simplified receipt (default - removes binary data, keeps execution results) receipt = client.wait_for_transaction_receipt( transaction_hash="0x...", - status=TransactionStatus.FINALIZED, + wait_until="finalized", full_transaction=False # Default - simplified for readability ) # Get complete receipt with all fields full_receipt = client.wait_for_transaction_receipt( transaction_hash="0x...", - status=TransactionStatus.FINALIZED, + wait_until="finalized", full_transaction=True # Complete receipt with all internal data ) ``` @@ -101,7 +116,7 @@ transaction_hash = client.write_contract( ) receipt = client.wait_for_transaction_receipt( hash=transaction_hash, - status=TransactionStatus.FINALIZED, // or ACCEPTED + wait_until="finalized", full_transaction=False // False by default - returns simplified receipt for better readability ) ``` @@ -117,7 +132,6 @@ estimate = client.estimate_transaction_fees( { "leaderTimeunitsAllocation": 100, "validatorTimeunitsAllocation": 200, - "rotations": [0], } ) @@ -133,6 +147,11 @@ tx_hash = client.write_contract( ) ``` +When `rotations` is omitted, estimates fund +`chain.default_consensus_max_rotations` for the initial round and every enabled +appeal round. Pass an explicit list, including `[0]`, when the application wants +to fund a different number of rotations. + If `fees["distribution"]` is provided without `feeValue`, the SDK derives the fee deposit from FeeManager on network backends, or from `sim_getFeeConfig` on Studio. Use `messageAllocations` with `estimate_transaction_fees` for @@ -254,18 +273,26 @@ client.top_up_fees( }, ) -client.top_up_and_submit_appeal( - transaction_id=tx_hash, - value=1_400, - distribution={ - "appealRounds": 1, - "rotations": [0, 0], - }, -) +quote = client.get_appeal_quote(tx_hash) +if client.can_appeal(tx_hash, expected_decision_id=quote["decision_id"]): + client.top_up_and_submit_appeal( + transaction_id=tx_hash, + expected_decision_id=quote["decision_id"], + value=quote["total"], + distribution={ + "appealRounds": 1, + "rotations": [0, 0], + }, + ) ``` `top_up_fees` returns the backend RPC hash. On network backends this is the EVM transaction hash; on Studio/localnet it is the target GenLayer transaction id. +Appeal commands are guarded by the quoted decision id so a stale request cannot +bind to a newer decision. If the id and value are omitted, the SDK refreshes +this lightweight quote automatically. This applies to deployed Consensus. +Current Studio uses its native decision-free appeal methods: pass ``value`` +explicitly and omit ``expected_decision_id``. ### Checking execution results @@ -274,13 +301,13 @@ A transaction can be finalized by consensus but still have a failed execution. A ```python from genlayer_py import create_client, create_account from genlayer_py.chains import testnet_bradbury -from genlayer_py.types import TransactionStatus, ExecutionResult +from genlayer_py.types import ExecutionResult client = create_client(chain=testnet_bradbury, account=create_account()) receipt = client.wait_for_transaction_receipt( transaction_hash=tx_hash, - status=TransactionStatus.FINALIZED, + wait_until="finalized", ) if receipt.get("tx_execution_result_name") == ExecutionResult.FINISHED_WITH_RETURN.value: @@ -305,6 +332,27 @@ Transactions can emit messages to other contracts. These messages create new chi ```python tx = client.get_transaction(transaction_hash=tx_hash) +# The default lifecycle is derived only from stored chain state. +print(tx["lifecycle"]) +# {"state": "processing", "phase": "revealing"} +# {"state": "decided", "outcome": "accepted"} + +# Protocol projection/action details are available only through the explicit +# advanced API. +raw_lifecycle = client.get_transaction_lifecycle(transaction_hash=tx_hash) +print(raw_lifecycle["stored_status_name"]) +print(raw_lifecycle["projected_status_name"]) +print(raw_lifecycle["resolution_action_name"]) +print(raw_lifecycle["resolution_source_name"]) +# `resolution_action_name == "Finalize"` is the authoritative readiness verdict. +# On current Studio without the advanced lifecycle RPC, only stored status is +# provable; projection repeats it and resolution/decision fields stay inactive. + +# The train stores the execution hash, not the old receipt bytes. +print(tx["tx_execution_hash"]) +# `tx_receipt` remains present but is `None` when the +# protocol cannot supply the old bytes. + # Messages emitted by the contract during execution print(tx["messages"]) # [{"messageType": 1, "recipient": "0x...", "value": 0, "data": "0x...", "onAcceptance": True, "saltNonce": 0}, ...] @@ -315,6 +363,20 @@ print(child_tx_ids) # ["0xabc...", "0xdef..."] ``` +### Active and joined validators + +The active set contains only validators currently eligible for protocol +duties. The joined registry is broader and can include validators that are not +yet selectable, are under-staked, or are otherwise unavailable. + +```python +active = client.active_validators() +active_count = client.active_validators_count() + +joined = client.joined_validators() +joined_count = client.joined_validators_count() +``` + ### Debugging transaction execution Use `debug_trace_transaction` to inspect the full execution trace of a transaction, including return data, errors, and GenVM logs: diff --git a/docs/BRANCHING.md b/docs/BRANCHING.md new file mode 100644 index 0000000..0b5b652 --- /dev/null +++ b/docs/BRANCHING.md @@ -0,0 +1,61 @@ +# Branching and Release Trains + +This repo follows the GenLayer release-train model. + +## Current Train + +- Current stable branch: `v0.18` +- Active integration branch: `v0.19-dev` +- Next stable target: `v0.19` +- `main`: default/static branch alias for the active integration branch + +## Stable Branches + +Stable branches are long-lived release lines. For semver-zero packages, each +minor line is treated as the release line, for example `v0.18` or `v0.19`. + +PRs may target a stable branch directly when the merged result should be +releasable immediately. This is appropriate for bug fixes, small non-breaking +features, isolated release fixes, or a breaking change that is intentionally +shipping as the next version by itself. + +Stable branches must remain releasable. PRs into stable branches are expected to +pass the required cross-repo `E2E Tests` gate before merge. + +## Integration Branches + +Integration branches are optional. Use one when multiple changes need to +accumulate before release, especially for cross-repo work, dependent features, +breaking changes that must ship together, or a train that needs advisory E2E +while still expected to be red. + +Integration branches are named after the target stable branch plus `-dev`, for +example `v0.19-dev`. Feature PRs for that train target the integration branch. + +PRs into integration branches may run `E2E Tests` as advisory checks. They are +not the release gate. + +## Promotion and Release + +When an integration train is ready, open a promotion PR from the integration +branch to the matching stable branch, for example `v0.19-dev` to `v0.19`. + +That promotion PR is the release-readiness gate and must pass required +cross-repo `E2E Tests`. The final package release is cut from the stable branch +using a version tag after the stable branch is ready. A release candidate may +be cut earlier from the matching integration branch; RC tags use +`vX.Y.Z-rc.N`, publish as PyPI prereleases, and never substitute for the +promotion PR's final release gate. + +## `main` + +`main` exists for GitHub UX and tools that require a stable default branch. It is +not a release branch and it is not the integration target. + +This repo keeps `main` forwarded to the active integration branch using +automation. PRs opened against `main` are automatically retargeted to the branch +listed in `support/ci/ACTIVE_DEV_BRANCH`. + +When changing the active integration branch, update +`support/ci/ACTIVE_DEV_BRANCH`, the repo docs, and the corresponding +`genlayer-e2e` release-train matrix in the same change set. diff --git a/docs/api-references/api.md b/docs/api-references/api.md index 92046fb..4c78224 100644 --- a/docs/api-references/api.md +++ b/docs/api-references/api.md @@ -64,19 +64,19 @@ client.initialize_consensus_smart_contract(force_reset: bool = False) Executes a read-only contract call without modifying state. ```python -client.read_contract(address: Union, function_name: str, args: Union = None, kwargs: Union = None, account: Union = None, raw_return: bool = False, transaction_hash_variant: TransactionHashVariant = , sim_config: Union = None) +client.read_contract(address: Union, function_name: str, args: Optional = None, kwargs: Optional = None, account: Optional = None, raw_return: bool = False, transaction_hash_variant: TransactionHashVariant = , sim_config: Optional = None) ``` | Parameter | Type | Required | Default | |-----------|------|----------|---------| | address | `Union` | yes | | | function_name | `str` | yes | | -| args | `Union` | no | None | -| kwargs | `Union` | no | None | -| account | `Union` | no | None | +| args | `Optional` | no | None | +| kwargs | `Optional` | no | None | +| account | `Optional` | no | None | | raw_return | `bool` | no | False | | transaction_hash_variant | `TransactionHashVariant` | no | | -| sim_config | `Union` | no | None | +| sim_config | `Optional` | no | None | --- @@ -85,20 +85,22 @@ client.read_contract(address: Union, function_name: str, args: Union = None, kwa Executes a state-modifying function on a contract through consensus. Returns the transaction hash. ```python -client.write_contract(address: Union, function_name: str, account: Union = None, consensus_max_rotations: Union = None, value: int = 0, leader_only: bool = False, args: Union = None, kwargs: Union = None, sim_config: Union = None) +client.write_contract(address: Union, function_name: str, account: Optional = None, consensus_max_rotations: Optional = None, value: int = 0, leader_only: bool = False, args: Optional = None, kwargs: Optional = None, sim_config: Optional = None, valid_until: Optional = None, fees: Optional = None) ``` | Parameter | Type | Required | Default | |-----------|------|----------|---------| | address | `Union` | yes | | | function_name | `str` | yes | | -| account | `Union` | no | None | -| consensus_max_rotations | `Union` | no | None | +| account | `Optional` | no | None | +| consensus_max_rotations | `Optional` | no | None | | value | `int` | no | 0 | | leader_only | `bool` | no | False | -| args | `Union` | no | None | -| kwargs | `Union` | no | None | -| sim_config | `Union` | no | None | +| args | `Optional` | no | None | +| kwargs | `Optional` | no | None | +| sim_config | `Optional` | no | None | +| valid_until | `Optional` | no | None | +| fees | `Optional` | no | None | --- @@ -107,17 +109,20 @@ client.write_contract(address: Union, function_name: str, account: Union = None, Simulates a state-modifying contract call without executing on-chain. Localnet only. ```python -client.simulate_write_contract(address: Union, function_name: str, account: Union = None, args: Union = None, kwargs: Union = None, sim_config: Union = None, transaction_hash_variant: TransactionHashVariant = ) +client.simulate_write_contract(address: Union, function_name: str, account: Optional = None, args: Optional = None, kwargs: Optional = None, value: int = 0, leader_only: bool = False, fees: Optional = None, sim_config: Optional = None, transaction_hash_variant: TransactionHashVariant = ) ``` | Parameter | Type | Required | Default | |-----------|------|----------|---------| | address | `Union` | yes | | | function_name | `str` | yes | | -| account | `Union` | no | None | -| args | `Union` | no | None | -| kwargs | `Union` | no | None | -| sim_config | `Union` | no | None | +| account | `Optional` | no | None | +| args | `Optional` | no | None | +| kwargs | `Optional` | no | None | +| value | `int` | no | 0 | +| leader_only | `bool` | no | False | +| fees | `Optional` | no | None | +| sim_config | `Optional` | no | None | | transaction_hash_variant | `TransactionHashVariant` | no | | --- @@ -127,18 +132,20 @@ client.simulate_write_contract(address: Union, function_name: str, account: Unio Deploys a new intelligent contract to GenLayer. Returns the transaction hash. ```python -client.deploy_contract(code: Union, account: Union = None, args: Union = None, kwargs: Union = None, consensus_max_rotations: Union = None, leader_only: bool = False, sim_config: Union = None) +client.deploy_contract(code: Union, account: Optional = None, args: Optional = None, kwargs: Optional = None, consensus_max_rotations: Optional = None, leader_only: bool = False, sim_config: Optional = None, valid_until: Optional = None, fees: Optional = None) ``` | Parameter | Type | Required | Default | |-----------|------|----------|---------| | code | `Union` | yes | | -| account | `Union` | no | None | -| args | `Union` | no | None | -| kwargs | `Union` | no | None | -| consensus_max_rotations | `Union` | no | None | +| account | `Optional` | no | None | +| args | `Optional` | no | None | +| kwargs | `Optional` | no | None | +| consensus_max_rotations | `Optional` | no | None | | leader_only | `bool` | no | False | -| sim_config | `Union` | no | None | +| sim_config | `Optional` | no | None | +| valid_until | `Optional` | no | None | +| fees | `Optional` | no | None | --- @@ -177,31 +184,180 @@ client.get_contract_schema_for_code(contract_code: AnyStr) ### appeal_transaction Appeals a consensus transaction to trigger a new round of validation. +Returns the original transaction_id (appeals operate on the same tx). +Missing decision/value inputs are filled from the authoritative quote +on both Studio and deployed Consensus. ```python -client.appeal_transaction(transaction_id: HexStr, account: Union = None, value: int = 0) +client.appeal_transaction(transaction_id: HexStr, account: Optional = None, value: Optional = None, expected_decision_id: Optional = None) ``` | Parameter | Type | Required | Default | |-----------|------|----------|---------| | transaction_id | `HexStr` | yes | | -| account | `Union` | no | None | -| value | `int` | no | 0 | +| account | `Optional` | no | None | +| value | `Optional` | no | None | +| expected_decision_id | `Optional` | no | None | + +--- + +### top_up_fees + +Deposits additional fee budget for an existing consensus transaction. + +```python +client.top_up_fees(transaction_id: HexStr, distribution: FeesDistributionInput, value: int, account: Optional = None) +``` + +| Parameter | Type | Required | Default | +|-----------|------|----------|---------| +| transaction_id | `HexStr` | yes | | +| distribution | `FeesDistributionInput` | yes | | +| value | `int` | yes | | +| account | `Optional` | no | None | + +**Returns:** `HexStr` + +--- + +### top_up_and_submit_appeal + +Deposits appeal funding and submits an appeal. + +Omitted decision/value inputs are resolved from the authoritative +appeal quote on both Studio and deployed Consensus. + +```python +client.top_up_and_submit_appeal(transaction_id: HexStr, distribution: FeesDistributionInput, account: Optional = None, value: Optional = None, expected_decision_id: Optional = None) +``` + +| Parameter | Type | Required | Default | +|-----------|------|----------|---------| +| transaction_id | `HexStr` | yes | | +| distribution | `FeesDistributionInput` | yes | | +| account | `Optional` | no | None | +| value | `Optional` | no | None | +| expected_decision_id | `Optional` | no | None | + +**Returns:** `HexStr` + +--- + +### can_appeal + +Checks whether the exact active decision can be appealed. + +```python +client.can_appeal(transaction_id: HexStr, expected_decision_id: Optional = None) +``` + +| Parameter | Type | Required | Default | +|-----------|------|----------|---------| +| transaction_id | `HexStr` | yes | | +| expected_decision_id | `Optional` | no | None | + +**Returns:** `bool` + +--- + +### get_appeal_quote + +Returns the latest decision id, appeal charges, and deadline. + +```python +client.get_appeal_quote(transaction_id: HexStr) +``` + +| Parameter | Type | Required | Default | +|-----------|------|----------|---------| +| transaction_id | `HexStr` | yes | | + +**Returns:** `Dict` + +--- + +### get_appeal_charge + +Returns the full appeal payment (bond plus induced-work funding). + +```python +client.get_appeal_charge(transaction_id: HexStr) +``` + +| Parameter | Type | Required | Default | +|-----------|------|----------|---------| +| transaction_id | `HexStr` | yes | | + +**Returns:** `int` + +--- + +### get_min_appeal_bond + +Deprecated alias for :meth:`get_appeal_charge`. + +```python +client.get_min_appeal_bond(transaction_id: HexStr) +``` + +| Parameter | Type | Required | Default | +|-----------|------|----------|---------| +| transaction_id | `HexStr` | yes | | + +**Returns:** `int` + +--- + +### wait_for_decision + +Poll until the stored transaction state is decided or terminal. + +```python +client.wait_for_decision(transaction_hash: Union, interval: int = 3000, retries: int = 10, full_transaction: bool = False) +``` + +| Parameter | Type | Required | Default | +|-----------|------|----------|---------| +| transaction_hash | `Union` | yes | | +| interval | `int` | no | 3000 | +| retries | `int` | no | 10 | +| full_transaction | `bool` | no | False | + +**Returns:** `GenLayerTransaction` + +--- + +### wait_for_finalization + +Poll until the stored transaction state is finalized. + +```python +client.wait_for_finalization(transaction_hash: Union, interval: int = 3000, retries: int = 10, full_transaction: bool = False) +``` + +| Parameter | Type | Required | Default | +|-----------|------|----------|---------| +| transaction_hash | `Union` | yes | | +| interval | `int` | no | 3000 | +| retries | `int` | no | 10 | +| full_transaction | `bool` | no | False | + +**Returns:** `GenLayerTransaction` --- ### wait_for_transaction_receipt -Polls until a transaction reaches the specified status. Returns the transaction receipt. +Poll for a stored decision (default) or stored finalization. ```python -client.wait_for_transaction_receipt(transaction_hash: Union, status: TransactionStatus = , interval: int = 3000, retries: int = 10, full_transaction: bool = False) +client.wait_for_transaction_receipt(transaction_hash: Union, wait_until: Literal = 'decided', interval: int = 3000, retries: int = 10, full_transaction: bool = False) ``` | Parameter | Type | Required | Default | |-----------|------|----------|---------| | transaction_hash | `Union` | yes | | -| status | `TransactionStatus` | no | | +| wait_until | `Literal` | no | 'decided' | | interval | `int` | no | 3000 | | retries | `int` | no | 10 | | full_transaction | `bool` | no | False | @@ -212,7 +368,12 @@ client.wait_for_transaction_receipt(transaction_hash: Union, status: Transaction ### get_transaction -Fetches transaction data including status, execution result, and consensus details. +Fetch transaction data with a stable stored-state ``lifecycle``. + +The lifecycle's ``state`` is one of processing, decided, finalized, or +canceled. Processing carries ``phase`` and decided carries ``outcome``. +The train exposes ``tx_execution_hash``; legacy receipt bytes are +unavailable, so ``tx_receipt`` is ``None``. ```python client.get_transaction(transaction_hash: Union) @@ -226,6 +387,27 @@ client.get_transaction(transaction_hash: Union) --- +### get_transaction_lifecycle + +Return advanced stored/projected/action protocol lifecycle data. + +If current Studio does not expose the advanced RPC, only its provable +stored status is returned: projection repeats it, resolution is +NoOp/Unspecified, and decision identity is inactive. + +```python +client.get_transaction_lifecycle(transaction_hash: Union, timestamp: Optional = None) +``` + +| Parameter | Type | Required | Default | +|-----------|------|----------|---------| +| transaction_hash | `Union` | yes | | +| timestamp | `Optional` | no | None | + +**Returns:** `ProtocolTransactionLifecycle` + +--- + ### get_triggered_transaction_ids Returns transaction IDs of child transactions created from emitted messages. @@ -261,29 +443,6 @@ client.debug_trace_transaction(transaction_hash: Union, round: int = 0) ## Types and Enums -### TransactionStatus - -Status of a GenLayer transaction in the consensus lifecycle. - -```python -TransactionStatus.UNINITIALIZED = "UNINITIALIZED" -TransactionStatus.PENDING = "PENDING" -TransactionStatus.PROPOSING = "PROPOSING" -TransactionStatus.COMMITTING = "COMMITTING" -TransactionStatus.REVEALING = "REVEALING" -TransactionStatus.ACCEPTED = "ACCEPTED" -TransactionStatus.UNDETERMINED = "UNDETERMINED" -TransactionStatus.FINALIZED = "FINALIZED" -TransactionStatus.CANCELED = "CANCELED" -TransactionStatus.APPEAL_REVEALING = "APPEAL_REVEALING" -TransactionStatus.APPEAL_COMMITTING = "APPEAL_COMMITTING" -TransactionStatus.READY_TO_FINALIZE = "READY_TO_FINALIZE" -TransactionStatus.VALIDATORS_TIMEOUT = "VALIDATORS_TIMEOUT" -TransactionStatus.LEADER_TIMEOUT = "LEADER_TIMEOUT" -``` - ---- - ### TransactionResult Consensus voting result across validators. @@ -297,6 +456,7 @@ TransactionResult.DETERMINISTIC_VIOLATION = "DETERMINISTIC_VIOLATION" TransactionResult.NO_MAJORITY = "NO_MAJORITY" TransactionResult.MAJORITY_AGREE = "MAJORITY_AGREE" TransactionResult.MAJORITY_DISAGREE = "MAJORITY_DISAGREE" +TransactionResult.MAJORITY_TIMEOUT = "MAJORITY_TIMEOUT" ``` --- @@ -309,28 +469,23 @@ Result of contract execution by the GenVM. ExecutionResult.NOT_VOTED = "NOT_VOTED" ExecutionResult.FINISHED_WITH_RETURN = "FINISHED_WITH_RETURN" ExecutionResult.FINISHED_WITH_ERROR = "FINISHED_WITH_ERROR" +ExecutionResult.TIMEOUT = "TIMEOUT" +ExecutionResult.NONDET_DISAGREE = "NONDET_DISAGREE" +ExecutionResult.DETERMINISTIC_VIOLATION = "DETERMINISTIC_VIOLATION" ``` --- ### VoteType -str(object='') -> str -str(bytes_or_buffer[, encoding[, errors]]) -> str - -Create a new string object from the given object. If encoding or -errors is specified, then the object must expose a data buffer -that will be decoded using the given encoding and error handler. -Otherwise, returns the result of object.__str__() (if defined) -or repr(object). -encoding defaults to 'utf-8'. -errors defaults to 'strict'. +Validator execution vote recorded for a consensus round. ```python VoteType.NOT_VOTED = "NOT_VOTED" -VoteType.AGREE = "AGREE" -VoteType.DISAGREE = "DISAGREE" +VoteType.FINISHED_WITH_RETURN = "FINISHED_WITH_RETURN" +VoteType.FINISHED_WITH_ERROR = "FINISHED_WITH_ERROR" VoteType.TIMEOUT = "TIMEOUT" +VoteType.NONDET_DISAGREE = "NONDET_DISAGREE" VoteType.DETERMINISTIC_VIOLATION = "DETERMINISTIC_VIOLATION" ``` diff --git a/docs/api-references/genlayer-py.md b/docs/api-references/genlayer-py.md index b844f06..7cca50f 100644 --- a/docs/api-references/genlayer-py.md +++ b/docs/api-references/genlayer-py.md @@ -192,16 +192,16 @@ client.appeal_transaction(transaction_id: HexStr, account: Union = None, value: ### wait_for_transaction_receipt -Polls until a transaction reaches the specified status. Returns the transaction receipt. +Polls for a stored decision by default, or for stored finalization. ```python -client.wait_for_transaction_receipt(transaction_hash: Union, status: TransactionStatus = , interval: int = 3000, retries: int = 10, full_transaction: bool = False) +client.wait_for_transaction_receipt(transaction_hash: Union, wait_until: Literal = "decided", interval: int = 3000, retries: int = 10, full_transaction: bool = False) ``` **Parameters:** - **transaction_hash** (`Union`) — required -- **status** (`TransactionStatus`) — optional = +- **wait_until** (`Literal["decided", "finalized"]`) — optional = "decided" - **interval** (`int`) — optional = 3000 - **retries** (`int`) — optional = 10 - **full_transaction** (`bool`) — optional = False @@ -210,9 +210,30 @@ client.wait_for_transaction_receipt(transaction_hash: Union, status: Transaction --- +### wait_for_decision + +Polls until the stored transaction state is decided, finalized, or canceled. + +```python +client.wait_for_decision(transaction_hash: Union, interval: int = 3000, retries: int = 10, full_transaction: bool = False) +``` + +--- + +### wait_for_finalization + +Polls until the stored transaction state is finalized. + +```python +client.wait_for_finalization(transaction_hash: Union, interval: int = 3000, retries: int = 10, full_transaction: bool = False) +``` + +--- + ### get_transaction -Fetches transaction data including status, execution result, and consensus details. +Fetches transaction data with a stable lifecycle derived from stored chain +state, plus execution result and consensus details. ```python client.get_transaction(transaction_hash: Union) @@ -224,6 +245,25 @@ client.get_transaction(transaction_hash: Union) **Returns:** `GenLayerTransaction` +`lifecycle` is discriminated by its `state` field: processing carries `phase`, +decided carries `outcome`, finalized may carry an outcome when it is actually +known, and canceled has no extra branch data. + +The train exposes the authoritative `tx_execution_hash`. It does not retain the +old receipt bytes, so the legacy `tx_receipt` field is `None`. + +--- + +### get_transaction_lifecycle + +Returns the advanced raw protocol view: stored status, projected status, +resolution action/source, decision identity, and evaluation time. A `FINALIZE` +action is the authoritative finalization-readiness verdict. + +```python +client.get_transaction_lifecycle(transaction_hash: Union) +``` + --- ### get_triggered_transaction_ids @@ -261,29 +301,6 @@ client.debug_trace_transaction(transaction_hash: Union, round: int = 0) ## Types and Enums -### TransactionStatus - -Status of a GenLayer transaction in the consensus lifecycle. - -```python -TransactionStatus.UNINITIALIZED = "UNINITIALIZED" -TransactionStatus.PENDING = "PENDING" -TransactionStatus.PROPOSING = "PROPOSING" -TransactionStatus.COMMITTING = "COMMITTING" -TransactionStatus.REVEALING = "REVEALING" -TransactionStatus.ACCEPTED = "ACCEPTED" -TransactionStatus.UNDETERMINED = "UNDETERMINED" -TransactionStatus.FINALIZED = "FINALIZED" -TransactionStatus.CANCELED = "CANCELED" -TransactionStatus.APPEAL_REVEALING = "APPEAL_REVEALING" -TransactionStatus.APPEAL_COMMITTING = "APPEAL_COMMITTING" -TransactionStatus.READY_TO_FINALIZE = "READY_TO_FINALIZE" -TransactionStatus.VALIDATORS_TIMEOUT = "VALIDATORS_TIMEOUT" -TransactionStatus.LEADER_TIMEOUT = "LEADER_TIMEOUT" -``` - ---- - ### TransactionResult Consensus voting result across validators. @@ -309,28 +326,23 @@ Result of contract execution by the GenVM. ExecutionResult.NOT_VOTED = "NOT_VOTED" ExecutionResult.FINISHED_WITH_RETURN = "FINISHED_WITH_RETURN" ExecutionResult.FINISHED_WITH_ERROR = "FINISHED_WITH_ERROR" +ExecutionResult.TIMEOUT = "TIMEOUT" +ExecutionResult.NONDET_DISAGREE = "NONDET_DISAGREE" +ExecutionResult.DETERMINISTIC_VIOLATION = "DETERMINISTIC_VIOLATION" ``` --- ### VoteType -str(object='') -> str -str(bytes_or_buffer[, encoding[, errors]]) -> str - -Create a new string object from the given object. If encoding or -errors is specified, then the object must expose a data buffer -that will be decoded using the given encoding and error handler. -Otherwise, returns the result of object.__str__() (if defined) -or repr(object). -encoding defaults to 'utf-8'. -errors defaults to 'strict'. +Validator execution vote recorded for a consensus round. ```python VoteType.NOT_VOTED = "NOT_VOTED" -VoteType.AGREE = "AGREE" -VoteType.DISAGREE = "DISAGREE" +VoteType.FINISHED_WITH_RETURN = "FINISHED_WITH_RETURN" +VoteType.FINISHED_WITH_ERROR = "FINISHED_WITH_ERROR" VoteType.TIMEOUT = "TIMEOUT" +VoteType.NONDET_DISAGREE = "NONDET_DISAGREE" VoteType.DETERMINISTIC_VIOLATION = "DETERMINISTIC_VIOLATION" ``` diff --git a/docs/api-references/index.md b/docs/api-references/index.md index 0df4eae..0e6124a 100644 --- a/docs/api-references/index.md +++ b/docs/api-references/index.md @@ -20,6 +20,22 @@ To install the GenLayerPY SDK, use the following command: $ pip install genlayer-py ``` +SDK releases follow their corresponding GenLayer protocol release. This +release targets the current resolution-kernel train; use the matching older SDK +release when connecting to an older deployment. + +Use the dedicated preview preset for the release-candidate Studio deployment: + +```python +from genlayer_py import create_client +from genlayer_py.chains import studio_devnet + +client = create_client(chain=studio_devnet) +``` + +`studio_devnet` targets `https://studio-dev.genlayer.com/api` (chain ID 61997). +The existing `studionet` preset remains pinned to the stable hosted Studio. + Here’s how to initialize the client and connect to the GenLayer Simulator: ### Reading a Transaction @@ -41,21 +57,20 @@ transaction = client.get_transaction(hash=transaction_hash) ```python from genlayer_py import create_client from genlayer_py.chains import localnet -from genlayer_py.types import TransactionStatus client = create_client(chain=localnet) # Get simplified receipt (default - removes binary data, keeps execution results) receipt = client.wait_for_transaction_receipt( transaction_hash="0x...", - status=TransactionStatus.FINALIZED, + wait_until="finalized", full_transaction=False # Default - simplified for readability ) # Get complete receipt with all fields full_receipt = client.wait_for_transaction_receipt( transaction_hash="0x...", - status=TransactionStatus.FINALIZED, + wait_until="finalized", full_transaction=True # Complete receipt with all internal data ) ``` @@ -98,11 +113,184 @@ transaction_hash = client.write_contract( ) receipt = client.wait_for_transaction_receipt( hash=transaction_hash, - status=TransactionStatus.FINALIZED, // or ACCEPTED + wait_until="finalized", full_transaction=False // False by default - returns simplified receipt for better readability ) ``` +### Fee presets for transactions + +Apps can build a trusted fee preset once they know the transaction shape, then +submit the same preset with the transaction. The user may still override these +values in wallet or app UI before signing. + +```python +estimate = client.estimate_transaction_fees( + { + "leaderTimeunitsAllocation": 100, + "validatorTimeunitsAllocation": 200, + } +) + +tx_hash = client.write_contract( + account=account, + address=contract_address, + function_name="update_storage", + args=["new_storage"], + fees={ + "distribution": estimate["distribution"], + "feeValue": estimate["feeValue"], + }, +) +``` + +When `rotations` is omitted, estimates fund +`chain.default_consensus_max_rotations` for the initial round and every enabled +appeal round. Pass an explicit list, including `[0]`, when the application wants +to fund a different number of rotations. + +If `fees["distribution"]` is provided without `feeValue`, the SDK derives the +fee deposit from FeeManager on network backends, or from `sim_getFeeConfig` on +Studio. Use `messageAllocations` with `estimate_transaction_fees` for +transactions that can emit funded messages. For method-specific message +budgets, derive the same call key GenVM reports in fee accounting: + +```python +from genlayer_py.transactions import ( + MessageType, + derive_external_message_call_key, + derive_internal_message_call_key, + encode_external_message_fee_params, + encode_internal_message_fee_params, +) + +estimate = client.estimate_transaction_fees( + { + "messageAllocations": [ + { + "messageType": MessageType.Internal, + "onAcceptance": True, + "recipient": contract_address, + "callKey": derive_internal_message_call_key("update_storage"), + "budget": 55, + "feeParams": encode_internal_message_fee_params(), + }, + { + "messageType": MessageType.External, + "onAcceptance": False, + "recipient": "0x3333333333333333333333333333333333333333", + "callKey": derive_external_message_call_key("0xaabbccdd"), + "budget": 210_000, + "feeParams": encode_external_message_fee_params( + {"gasLimit": 21_000, "maxGasPrice": 10} + ), + }, + ], + } +) +``` + +For a concrete Studio/localnet write, use the one-call helper. The SDK sends an +initial fee budget to `sim_estimateTransactionFees`; Studio simulates the write +without committing state and returns the authoritative recommended preset. + +```python +recommended = client.estimate_transaction_fees_for_write( + account=account, + address=contract_address, + function_name="update_storage", + args=["new_storage"], +) + +tx_hash = client.write_contract( + account=account, + address=contract_address, + function_name="update_storage", + args=["new_storage"], + fees={ + "distribution": recommended["distribution"], + "messageAllocations": recommended.get("messageAllocations"), + "feeValue": recommended["feeValue"], + }, +) +``` + +For tests or tools that need to inspect the raw simulation, use the explicit +two-step flow. `simulate_write_contract` uses `sim_call`; the returned receipt +includes the fee accounting report produced by GenVM and Studio: + +```python +simulation = client.simulate_write_contract( + account=account, + address=contract_address, + function_name="update_storage", + args=["new_storage"], + fees={ + "distribution": estimate["distribution"], + "feeValue": estimate["feeValue"], + }, +) + +print(simulation["genvm_result"]["fee_accounting"]) +``` + +To reuse a representative Studio simulation as the trusted preset source, pass +the simulation result into `estimate_transaction_fees_from_simulation`: + +```python +estimate = client.estimate_transaction_fees_from_simulation( + { + "simulation": simulation, + } +) + +tx_hash = client.write_contract( + account=account, + address=contract_address, + function_name="update_storage", + args=["new_storage"], + fees={ + "distribution": estimate["distribution"], + "messageAllocations": estimate.get("messageAllocations"), + "feeValue": estimate["feeValue"], + }, +) +``` + +For transactions that are already submitted, use the fee-management helpers: + +```python +client.top_up_fees( + transaction_id=tx_hash, + value=1_100, + distribution={ + "leaderTimeunitsAllocation": 100, + "validatorTimeunitsAllocation": 200, + "rotations": [0], + }, +) + +quote = client.get_appeal_quote(tx_hash) +if client.can_appeal(tx_hash, expected_decision_id=quote["decision_id"]): + client.top_up_and_submit_appeal( + transaction_id=tx_hash, + expected_decision_id=quote["decision_id"], + value=quote["total"], + distribution={ + "appealRounds": 1, + "rotations": [0, 0], + }, + ) +``` + +`top_up_fees` returns the backend RPC hash. On network backends this is the EVM +transaction hash; on Studio/localnet it is the target GenLayer transaction id. +Appeal commands are guarded by the quoted decision id so a stale request cannot +bind to a newer decision. If the id and value are omitted, the SDK refreshes +this lightweight quote automatically. This applies to deployed Consensus. +Current Studio uses its native decision-free appeal methods: pass ``value`` +explicitly and omit ``expected_decision_id``. + ### Checking execution results A transaction can be finalized by consensus but still have a failed execution. Always check `tx_execution_result` before reading contract state: @@ -110,13 +298,13 @@ A transaction can be finalized by consensus but still have a failed execution. A ```python from genlayer_py import create_client, create_account from genlayer_py.chains import testnet_bradbury -from genlayer_py.types import TransactionStatus, ExecutionResult +from genlayer_py.types import ExecutionResult client = create_client(chain=testnet_bradbury, account=create_account()) receipt = client.wait_for_transaction_receipt( transaction_hash=tx_hash, - status=TransactionStatus.FINALIZED, + wait_until="finalized", ) if receipt.get("tx_execution_result_name") == ExecutionResult.FINISHED_WITH_RETURN.value: @@ -141,6 +329,27 @@ Transactions can emit messages to other contracts. These messages create new chi ```python tx = client.get_transaction(transaction_hash=tx_hash) +# The default lifecycle is derived only from stored chain state. +print(tx["lifecycle"]) +# {"state": "processing", "phase": "revealing"} +# {"state": "decided", "outcome": "accepted"} + +# Protocol projection/action details are available only through the explicit +# advanced API. +raw_lifecycle = client.get_transaction_lifecycle(transaction_hash=tx_hash) +print(raw_lifecycle["stored_status_name"]) +print(raw_lifecycle["projected_status_name"]) +print(raw_lifecycle["resolution_action_name"]) +print(raw_lifecycle["resolution_source_name"]) +# `resolution_action_name == "Finalize"` is the authoritative readiness verdict. +# On current Studio without the advanced lifecycle RPC, only stored status is +# provable; projection repeats it and resolution/decision fields stay inactive. + +# The train stores the execution hash, not the old receipt bytes. +print(tx["tx_execution_hash"]) +# `tx_receipt` remains present but is `None` when the +# protocol cannot supply the old bytes. + # Messages emitted by the contract during execution print(tx["messages"]) # [{"messageType": 1, "recipient": "0x...", "value": 0, "data": "0x...", "onAcceptance": True, "saltNonce": 0}, ...] @@ -151,6 +360,20 @@ print(child_tx_ids) # ["0xabc...", "0xdef..."] ``` +### Active and joined validators + +The active set contains only validators currently eligible for protocol +duties. The joined registry is broader and can include validators that are not +yet selectable, are under-staked, or are otherwise unavailable. + +```python +active = client.active_validators() +active_count = client.active_validators_count() + +joined = client.joined_validators() +joined_count = client.joined_validators_count() +``` + ### Debugging transaction execution Use `debug_trace_transaction` to inspect the full execution trace of a transaction, including return data, errors, and GenVM logs: diff --git a/genlayer_py/abi/calldata/decoder.py b/genlayer_py/abi/calldata/decoder.py index c993ac8..0772217 100644 --- a/genlayer_py/abi/calldata/decoder.py +++ b/genlayer_py/abi/calldata/decoder.py @@ -8,11 +8,24 @@ def decode(mem0: Buffer) -> CalldataEncodable: mem: memoryview = memoryview(mem0) + def take(length: int, label: str) -> memoryview: + nonlocal mem + if len(mem) < length: + raise GenLayerError( + f"truncated calldata while reading {label}: " + f"expected {length} bytes, found {len(mem)}" + ) + result = mem[:length] + mem = mem[length:] + return result + def read_uleb128() -> int: nonlocal mem ret = 0 off = 0 while True: + if len(mem) == 0: + raise GenLayerError("unexpected end of calldata while reading ULEB128") m = mem[0] ret = ret | ((m & 0x7F) << off) off += 7 @@ -33,9 +46,7 @@ def impl() -> CalldataEncodable: if code == consts.SPECIAL_TRUE: return True if code == consts.SPECIAL_ADDR: - ret_addr = mem[: CalldataAddress.SIZE] - mem = mem[CalldataAddress.SIZE :] - return CalldataAddress(ret_addr) + return CalldataAddress(take(CalldataAddress.SIZE, "address")) raise GenLayerError(f"Unknown special {bin(code)} {hex(code)}") code = code >> 3 if typ == consts.TYPE_PINT: @@ -43,12 +54,9 @@ def impl() -> CalldataEncodable: elif typ == consts.TYPE_NINT: return -code - 1 elif typ == consts.TYPE_BYTES: - ret_bytes = mem[:code] - mem = mem[code:] - return ret_bytes + return take(code, "bytes") elif typ == consts.TYPE_STR: - ret_str = mem[:code] - mem = mem[code:] + ret_str = take(code, "string") return str(ret_str, encoding="utf-8") elif typ == consts.TYPE_ARR: ret_arr = [] @@ -60,8 +68,7 @@ def impl() -> CalldataEncodable: prev = None for _i in range(code): le = read_uleb128() - key = str(mem[:le], encoding="utf-8") - mem = mem[le:] + key = str(take(le, "map key"), encoding="utf-8") if prev is not None: assert prev < key prev = key diff --git a/genlayer_py/accounts/actions.py b/genlayer_py/accounts/actions.py index 55b7091..56ae085 100644 --- a/genlayer_py/accounts/actions.py +++ b/genlayer_py/accounts/actions.py @@ -1,7 +1,7 @@ from __future__ import annotations from typing import TYPE_CHECKING -from genlayer_py.chains import localnet +from genlayer_py.chains.utils import is_studio_chain from hexbytes import HexBytes from web3.types import Nonce, BlockIdentifier, ENS from genlayer_py.exceptions import GenLayerError @@ -18,8 +18,8 @@ def fund_account( self: GenLayerClient, address: Union[Address, ChecksumAddress, ENS], amount: int ) -> HexBytes: - if self.chain.id != localnet.id: - raise GenLayerError("Client is not connected to the localhost") + if not is_studio_chain(self.chain): + raise GenLayerError("Account funding is only supported on Studio networks") try: response = self.provider.make_request( method="sim_fundAccount", @@ -38,4 +38,9 @@ def get_current_nonce( if address is None and self.account is None: raise GenLayerError("No address provided and no account is connected") address_to_use = address or self.account.address - return self.get_transaction_count(address_to_use, block_identifier) + # Include locally pending transactions by default so consecutive + # submissions do not reuse the same nonce before the first is mined. + resolved_block_identifier = ( + "pending" if block_identifier is None else block_identifier + ) + return self.get_transaction_count(address_to_use, resolved_block_identifier) diff --git a/genlayer_py/chains/__init__.py b/genlayer_py/chains/__init__.py index 9ff2d87..15daadc 100644 --- a/genlayer_py/chains/__init__.py +++ b/genlayer_py/chains/__init__.py @@ -2,5 +2,12 @@ from .testnet_asimov import testnet_asimov from .testnet_bradbury import testnet_bradbury from .studionet import studionet +from .studio_devnet import studio_devnet -__all__ = ["localnet", "testnet_asimov", "testnet_bradbury", "studionet"] +__all__ = [ + "localnet", + "testnet_asimov", + "testnet_bradbury", + "studionet", + "studio_devnet", +] diff --git a/genlayer_py/chains/actions.py b/genlayer_py/chains/actions.py index d387ab8..1c45cf8 100644 --- a/genlayer_py/chains/actions.py +++ b/genlayer_py/chains/actions.py @@ -1,9 +1,8 @@ from __future__ import annotations from genlayer_py.exceptions import GenLayerError -from .localnet import localnet -from .studionet import studionet from .testnet_asimov import testnet_asimov +from .utils import is_studio_chain from typing import TYPE_CHECKING @@ -23,12 +22,10 @@ def initialize_consensus_smart_contract( and bool(self.chain.consensus_main_contract.get("address")) and bool(self.chain.consensus_main_contract.get("abi")) ) - is_local_or_studio_chain = self.chain.id in (localnet.id, studionet.id) - if ( not force_reset and has_static_consensus_contract - and not is_local_or_studio_chain + and not is_studio_chain(self.chain) ): return diff --git a/genlayer_py/chains/localnet.py b/genlayer_py/chains/localnet.py index e23c9b1..10dbf13 100644 --- a/genlayer_py/chains/localnet.py +++ b/genlayer_py/chains/localnet.py @@ -16,7 +16,7 @@ } localnet: GenLayerChain = GenLayerChain( - id=61999, + id=61127, name="GenLayer Localnet", rpc_urls={ "default": { diff --git a/genlayer_py/chains/studio_devnet.py b/genlayer_py/chains/studio_devnet.py new file mode 100644 index 0000000..cd3da4c --- /dev/null +++ b/genlayer_py/chains/studio_devnet.py @@ -0,0 +1,32 @@ +from genlayer_py.types import GenLayerChain, NativeCurrency + +from .studionet import ( + CONSENSUS_DATA_CONTRACT, + CONSENSUS_MAIN_CONTRACT, +) + + +STUDIO_DEVNET_JSON_RPC_URL = "https://studio-dev.genlayer.com/api" +STUDIO_DEVNET_EXPLORER_URL = "https://explorer-studio-dev.genlayer.com" + +studio_devnet: GenLayerChain = GenLayerChain( + id=61997, + name="GenLayer Studio Devnet", + rpc_urls={"default": {"http": [STUDIO_DEVNET_JSON_RPC_URL]}}, + native_currency=NativeCurrency(name="GEN Token", symbol="GEN", decimals=18), + block_explorers={ + "default": { + "name": "GenLayer Explorer", + "url": STUDIO_DEVNET_EXPLORER_URL, + } + }, + testnet=True, + consensus_main_contract=dict(CONSENSUS_MAIN_CONTRACT), + consensus_data_contract=dict(CONSENSUS_DATA_CONTRACT), + fee_manager_contract=None, + rounds_storage_contract=None, + appeals_contract=None, + staking_contract=None, + default_number_of_initial_validators=5, + default_consensus_max_rotations=3, +) diff --git a/genlayer_py/chains/testnet_asimov.py b/genlayer_py/chains/testnet_asimov.py index 794f294..4a06e6d 100644 --- a/genlayer_py/chains/testnet_asimov.py +++ b/genlayer_py/chains/testnet_asimov.py @@ -1,6 +1,9 @@ -from genlayer_py.types import GenLayerChain, NativeCurrency -from genlayer_py.consensus.abi import CONSENSUS_MAIN_ABI, CONSENSUS_DATA_ABI - +from genlayer_py.types import GenLayerChain, NativeCurrency, SimpleContractInfo +from genlayer_py.consensus.abi import ( + APPEALS_ABI, + CONSENSUS_MAIN_ABI, + CONSENSUS_DATA_ABI, +) TESTNET_JSON_RPC_URL = "https://rpc-asimov.genlayer.com" EXPLORER_URL = "https://explorer-asimov.genlayer.com/" @@ -17,6 +20,95 @@ "bytecode": "", } +FEE_MANAGER_CONTRACT: SimpleContractInfo = { + "address": "0x21737AA4bea8FF12E202BF1BAB23751A95617533", + "abi": [ + { + "type": "function", + "name": "calculateMinAppealBond", + "stateMutability": "view", + "inputs": [ + {"name": "_txId", "type": "bytes32"}, + {"name": "_round", "type": "uint256"}, + {"name": "_status", "type": "uint8"}, + ], + "outputs": [{"name": "totalFeesToPay", "type": "uint256"}], + }, + ], +} + +ROUNDS_STORAGE_CONTRACT: SimpleContractInfo = { + "address": "0x1F595c0D549DE0812F127508ea1039636CFA62Cc", + "abi": [ + { + "type": "function", + "name": "getRoundNumber", + "stateMutability": "view", + "inputs": [{"name": "txId", "type": "bytes32"}], + "outputs": [{"name": "", "type": "uint256"}], + }, + { + "type": "function", + "name": "getRoundData", + "stateMutability": "view", + "inputs": [ + {"name": "txId", "type": "bytes32"}, + {"name": "round", "type": "uint256"}, + ], + "outputs": [ + { + "name": "", + "type": "tuple", + "components": [ + {"name": "round", "type": "uint256"}, + {"name": "leaderIndex", "type": "uint256"}, + {"name": "votesCommitted", "type": "uint256"}, + {"name": "votesRevealed", "type": "uint256"}, + {"name": "appealBond", "type": "uint256"}, + {"name": "rotationsLeft", "type": "uint256"}, + {"name": "result", "type": "uint8"}, + {"name": "roundValidators", "type": "address[]"}, + {"name": "validatorVotes", "type": "uint8[]"}, + {"name": "validatorVotesHash", "type": "bytes32[]"}, + {"name": "validatorResultHash", "type": "bytes32[]"}, + ], + } + ], + }, + { + "type": "function", + "name": "getLastRoundData", + "stateMutability": "view", + "inputs": [{"name": "txId", "type": "bytes32"}], + "outputs": [ + {"name": "round", "type": "uint256"}, + { + "name": "roundData", + "type": "tuple", + "components": [ + {"name": "round", "type": "uint256"}, + {"name": "leaderIndex", "type": "uint256"}, + {"name": "votesCommitted", "type": "uint256"}, + {"name": "votesRevealed", "type": "uint256"}, + {"name": "appealBond", "type": "uint256"}, + {"name": "rotationsLeft", "type": "uint256"}, + {"name": "result", "type": "uint8"}, + {"name": "roundValidators", "type": "address[]"}, + {"name": "validatorVotes", "type": "uint8[]"}, + {"name": "validatorVotesHash", "type": "bytes32[]"}, + {"name": "validatorResultHash", "type": "bytes32[]"}, + ], + }, + ], + }, + ], +} + +APPEALS_CONTRACT: SimpleContractInfo = { + "address": "0x0F739Dd8f5322b9547c7d19a9621BC2ac8DF4089", + "abi": APPEALS_ABI, +} + testnet_asimov: GenLayerChain = GenLayerChain( id=4221, @@ -34,9 +126,9 @@ testnet=True, consensus_main_contract=CONSENSUS_MAIN_CONTRACT, consensus_data_contract=CONSENSUS_DATA_CONTRACT, - fee_manager_contract=None, - rounds_storage_contract=None, - appeals_contract=None, + fee_manager_contract=FEE_MANAGER_CONTRACT, + rounds_storage_contract=ROUNDS_STORAGE_CONTRACT, + appeals_contract=APPEALS_CONTRACT, staking_contract=None, default_number_of_initial_validators=5, default_consensus_max_rotations=3, diff --git a/genlayer_py/chains/testnet_bradbury.py b/genlayer_py/chains/testnet_bradbury.py index 352bf3c..44ed0a1 100644 --- a/genlayer_py/chains/testnet_bradbury.py +++ b/genlayer_py/chains/testnet_bradbury.py @@ -1,19 +1,27 @@ -from genlayer_py.types import GenLayerChain, NativeCurrency, ContractInfo, SimpleContractInfo -from genlayer_py.consensus.abi import CONSENSUS_MAIN_ABI_V06, CONSENSUS_DATA_ABI_V06 - +from genlayer_py.types import ( + GenLayerChain, + NativeCurrency, + ContractInfo, + SimpleContractInfo, +) +from genlayer_py.consensus.abi import ( + APPEALS_ABI, + CONSENSUS_MAIN_ABI, + CONSENSUS_DATA_ABI, +) TESTNET_JSON_RPC_URL = "https://rpc-bradbury.genlayer.com" EXPLORER_URL = "https://explorer-bradbury.genlayer.com/" CONSENSUS_MAIN_CONTRACT: ContractInfo = { "address": "0x0112Bf6e83497965A5fdD6Dad1E447a6E004271D", - "abi": CONSENSUS_MAIN_ABI_V06, + "abi": CONSENSUS_MAIN_ABI, "bytecode": "", } CONSENSUS_DATA_CONTRACT: ContractInfo = { "address": "0x85D7bf947A512Fc640C75327A780c90847267697", - "abi": CONSENSUS_DATA_ABI_V06, + "abi": CONSENSUS_DATA_ABI, "bytecode": "", } @@ -103,15 +111,7 @@ APPEALS_CONTRACT: SimpleContractInfo = { "address": "0xbb8C35AA878D09b9830aFF9e5aAC6492BFbd5471", - "abi": [ - { - "type": "function", - "name": "canAppeal", - "stateMutability": "view", - "inputs": [{"name": "_txId", "type": "bytes32"}], - "outputs": [{"name": "", "type": "bool"}], - }, - ], + "abi": APPEALS_ABI, } diff --git a/genlayer_py/chains/utils.py b/genlayer_py/chains/utils.py new file mode 100644 index 0000000..c339e3a --- /dev/null +++ b/genlayer_py/chains/utils.py @@ -0,0 +1,12 @@ +from __future__ import annotations + +from genlayer_py.types import GenLayerChain + + +STUDIO_CHAIN_IDS = frozenset({61127, 61997, 61999}) + + +def is_studio_chain(chain: GenLayerChain) -> bool: + """Return whether *chain* uses the Studio simulator RPC surface.""" + + return chain.id in STUDIO_CHAIN_IDS diff --git a/genlayer_py/client/client.py b/genlayer_py/client/client.py index 3d6d833..92d3e1c 100644 --- a/genlayer_py/client/client.py +++ b/genlayer_py/client/client.py @@ -1,3 +1,4 @@ +from copy import deepcopy from typing import Optional from genlayer_py.types import GenLayerChain from genlayer_py.chains import localnet @@ -10,7 +11,7 @@ def create_client( endpoint: Optional[str] = None, account: Optional[LocalAccount] = None, ) -> GenLayerClient: - chain_config = chain or localnet + chain_config = deepcopy(chain or localnet) if endpoint is not None: chain_config.rpc_urls["default"]["http"] = [endpoint] client = GenLayerClient(chain_config, account) diff --git a/genlayer_py/client/genlayer_client.py b/genlayer_py/client/genlayer_client.py index aae6275..9622052 100644 --- a/genlayer_py/client/genlayer_client.py +++ b/genlayer_py/client/genlayer_client.py @@ -4,10 +4,9 @@ from eth_typing import Address, ChecksumAddress, HexStr from eth_account.signers.local import LocalAccount from hexbytes import HexBytes -from typing import AnyStr +from typing import AnyStr, Literal from genlayer_py.types import ( GenLayerChain, - TransactionStatus, CalldataEncodable, GenLayerTransaction, ContractSchema, @@ -28,6 +27,8 @@ get_round_data, get_last_round_data, can_appeal, + get_appeal_quote, + get_appeal_charge, get_min_appeal_bond, get_contract_schema, get_contract_schema_for_code, @@ -40,11 +41,15 @@ ) from genlayer_py.chains.actions import initialize_consensus_smart_contract from genlayer_py.transactions.actions import ( + wait_for_decision, + wait_for_finalization, wait_for_transaction_receipt, get_transaction, + get_transaction_lifecycle, get_triggered_transaction_ids, debug_trace_transaction, ) +from genlayer_py.types.transactions import ProtocolTransactionLifecycle from genlayer_py.staking.actions import ( validator_join, validator_deposit, @@ -52,6 +57,12 @@ validator_claim, validator_prime, set_operator, + get_operator_transfer_context, + get_validator_join_context, + initiate_operator_transfer, + complete_operator_transfer, + cancel_operator_transfer, + get_pending_operator, set_identity, delegator_join, delegator_exit, @@ -59,6 +70,8 @@ epoch as staking_epoch, active_validators, active_validators_count, + joined_validators, + joined_validators_count, is_validator, get_validator_info, get_stake_info, @@ -66,6 +79,10 @@ validator_min_stake, delegator_min_stake, ) +from genlayer_py.staking.operator_registration import ( + OperatorRegistrationContext, + OperatorRegistrationProof, +) from genlayer_py.config import transaction_config from genlayer_py.transactions.fees import ( FeeEstimateOptions, @@ -302,8 +319,8 @@ def top_up_fees( self, transaction_id: HexStr, distribution: FeesDistributionInput, + value: int, account: Optional[LocalAccount] = None, - value: int = 0, ) -> HexStr: """Deposits additional fee budget for an existing consensus transaction.""" return top_up_fees( @@ -319,31 +336,69 @@ def top_up_and_submit_appeal( transaction_id: HexStr, distribution: FeesDistributionInput, account: Optional[LocalAccount] = None, - value: int = 0, + value: Optional[int] = None, + expected_decision_id: Optional[int] = None, ) -> HexStr: - """Deposits appeal fee budget and submits an appeal in one consensus call.""" + """Deposits appeal funding and submits an appeal. + + Omitted decision/value inputs are resolved from the authoritative + appeal quote on both Studio and deployed Consensus. + """ return top_up_and_submit_appeal( self=self, transaction_id=transaction_id, distribution=distribution, account=account, value=value, + expected_decision_id=expected_decision_id, ) # Transaction actions def wait_for_transaction_receipt( self, transaction_hash: _Hash32, - status: TransactionStatus = TransactionStatus.ACCEPTED, + wait_until: Literal["decided", "finalized"] = "decided", interval: int = transaction_config.wait_interval, retries: int = transaction_config.retries, full_transaction: bool = False, ) -> GenLayerTransaction: - """Polls until a transaction reaches the specified status. Returns the transaction receipt.""" + """Poll for a stored decision (default) or stored finalization.""" return wait_for_transaction_receipt( self=self, transaction_hash=transaction_hash, - status=status, + wait_until=wait_until, + interval=interval, + retries=retries, + full_transaction=full_transaction, + ) + + def wait_for_decision( + self, + transaction_hash: _Hash32, + interval: int = transaction_config.wait_interval, + retries: int = transaction_config.retries, + full_transaction: bool = False, + ) -> GenLayerTransaction: + """Poll until the stored transaction state is decided or terminal.""" + return wait_for_decision( + self=self, + transaction_hash=transaction_hash, + interval=interval, + retries=retries, + full_transaction=full_transaction, + ) + + def wait_for_finalization( + self, + transaction_hash: _Hash32, + interval: int = transaction_config.wait_interval, + retries: int = transaction_config.retries, + full_transaction: bool = False, + ) -> GenLayerTransaction: + """Poll until the stored transaction state is finalized.""" + return wait_for_finalization( + self=self, + transaction_hash=transaction_hash, interval=interval, retries=retries, full_transaction=full_transaction, @@ -353,15 +408,40 @@ def get_transaction( self, transaction_hash: _Hash32, ) -> GenLayerTransaction: - """Fetches transaction data including status, execution result, and consensus details.""" + """Fetch transaction data with a stable stored-state ``lifecycle``. + + The lifecycle's ``state`` is one of processing, decided, finalized, or + canceled. Processing carries ``phase`` and decided carries ``outcome``. + The train exposes ``tx_execution_hash``; legacy receipt bytes are + unavailable, so ``tx_receipt`` is ``None``. + """ return get_transaction(self=self, transaction_hash=transaction_hash) + def get_transaction_lifecycle( + self, + transaction_hash: _Hash32, + timestamp: Optional[int] = None, + ) -> ProtocolTransactionLifecycle: + """Return advanced stored/projected/action protocol lifecycle data. + + If current Studio does not expose the advanced RPC, only its provable + stored status is returned: projection repeats it, resolution is + NoOp/Unspecified, and decision identity is inactive. + """ + return get_transaction_lifecycle( + self=self, + transaction_hash=transaction_hash, + timestamp=timestamp, + ) + def get_triggered_transaction_ids( self, transaction_hash: _Hash32, ) -> list: """Returns transaction IDs of child transactions created from emitted messages.""" - return get_triggered_transaction_ids(self=self, transaction_hash=transaction_hash) + return get_triggered_transaction_ids( + self=self, transaction_hash=transaction_hash + ) def debug_trace_transaction( self, @@ -369,21 +449,28 @@ def debug_trace_transaction( round: int = 0, ) -> dict: """Fetches the full execution trace including return data, stdout, stderr, and GenVM logs.""" - return debug_trace_transaction(self=self, transaction_hash=transaction_hash, round=round) + return debug_trace_transaction( + self=self, transaction_hash=transaction_hash, round=round + ) def appeal_transaction( self, transaction_id: HexStr, account: Optional[LocalAccount] = None, - value: int = 0, + value: Optional[int] = None, + expected_decision_id: Optional[int] = None, ): """Appeals a consensus transaction to trigger a new round of validation. - Returns the original transaction_id (appeals operate on the same tx).""" + Returns the original transaction_id (appeals operate on the same tx). + Missing decision/value inputs are filled from the authoritative quote + on both Studio and deployed Consensus. + """ return appeal_transaction( self=self, transaction_id=transaction_id, account=account, value=value, + expected_decision_id=expected_decision_id, ) def get_round_number(self, transaction_id: HexStr) -> int: @@ -398,12 +485,28 @@ def get_last_round_data(self, transaction_id: HexStr) -> tuple: """Returns the current round number and its data.""" return get_last_round_data(self=self, transaction_id=transaction_id) - def can_appeal(self, transaction_id: HexStr) -> bool: - """Checks if a transaction can be appealed.""" - return can_appeal(self=self, transaction_id=transaction_id) + def can_appeal( + self, + transaction_id: HexStr, + expected_decision_id: Optional[int] = None, + ) -> bool: + """Checks whether the exact active decision can be appealed.""" + return can_appeal( + self=self, + transaction_id=transaction_id, + expected_decision_id=expected_decision_id, + ) + + def get_appeal_quote(self, transaction_id: HexStr) -> Dict[str, int]: + """Returns the latest decision id, appeal charges, and deadline.""" + return get_appeal_quote(self=self, transaction_id=transaction_id) + + def get_appeal_charge(self, transaction_id: HexStr) -> int: + """Returns the full appeal payment (bond plus induced-work funding).""" + return get_appeal_charge(self=self, transaction_id=transaction_id) def get_min_appeal_bond(self, transaction_id: HexStr) -> int: - """Calculates the minimum bond required to appeal a transaction.""" + """Deprecated alias for :meth:`get_appeal_charge`.""" return get_min_appeal_bond(self=self, transaction_id=transaction_id) # ── Staking actions (EVM, not consensus-layer) ──────────────────── @@ -415,12 +518,21 @@ def staking_epoch(self) -> int: return staking_epoch(self=self) def active_validators(self) -> List: - """Returns ValidatorWallet addresses active in the current epoch.""" + """Returns ValidatorWallet addresses currently eligible for duties.""" return active_validators(self=self) def active_validators_count(self) -> int: + """Returns the number of validators currently eligible for duties.""" return active_validators_count(self=self) + def joined_validators(self) -> List: + """Returns every ValidatorWallet in the append-only joined registry.""" + return joined_validators(self=self) + + def joined_validators_count(self) -> int: + """Returns the size of the append-only joined validator registry.""" + return joined_validators_count(self=self) + def is_validator(self, address) -> bool: return is_validator(self=self, address=address) @@ -444,15 +556,25 @@ def delegator_min_stake(self) -> int: def validator_join( self, amount: int, - operator=None, + registration: Optional[OperatorRegistrationProof] = None, account: Optional[LocalAccount] = None, + operator=None, ) -> HexBytes: - """Joins as a validator. Deploys a ValidatorWallet with msg.sender - as owner and `operator` (defaults to owner) as operator.""" + """Joins with a proof-bound operator key and deploys a ValidatorWallet.""" return validator_join( - self=self, amount=amount, operator=operator, account=account + self=self, + amount=amount, + registration=registration, + account=account, + operator=operator, ) + def get_validator_join_context( + self, account: Optional[LocalAccount] = None + ) -> OperatorRegistrationContext: + """Factory-bound context for building a validator join proof.""" + return get_validator_join_context(self=self, account=account) + def validator_deposit( self, validator, amount: int, account: Optional[LocalAccount] = None ) -> HexBytes: @@ -483,11 +605,41 @@ def validator_prime( def set_operator( self, validator, operator, account: Optional[LocalAccount] = None ) -> HexBytes: - """Rotates the operator for an existing ValidatorWallet.""" + """Raises with migration guidance for proof-based operator rotation.""" return set_operator( self=self, validator=validator, operator=operator, account=account ) + def get_operator_transfer_context(self, validator): + """Wallet-bound context for building a rotation proof.""" + return get_operator_transfer_context(self=self, validator=validator) + + def initiate_operator_transfer( + self, validator, registration, account: Optional[LocalAccount] = None + ) -> HexBytes: + """Starts the two-step operator rotation (CON-715).""" + return initiate_operator_transfer( + self=self, validator=validator, registration=registration, account=account + ) + + def complete_operator_transfer( + self, validator, account: Optional[LocalAccount] = None + ) -> HexBytes: + """Finalises a pending operator rotation.""" + return complete_operator_transfer( + self=self, validator=validator, account=account + ) + + def cancel_operator_transfer( + self, validator, account: Optional[LocalAccount] = None + ) -> HexBytes: + """Abandons a pending operator rotation.""" + return cancel_operator_transfer(self=self, validator=validator, account=account) + + def get_pending_operator(self, validator) -> dict: + """Pending operator and when its transfer was initiated.""" + return get_pending_operator(self=self, validator=validator) + def set_identity( self, validator, moniker: str, account: Optional[LocalAccount] = None ) -> HexBytes: diff --git a/genlayer_py/consensus/abi/__init__.py b/genlayer_py/consensus/abi/__init__.py index 86bef2c..5c5c920 100644 --- a/genlayer_py/consensus/abi/__init__.py +++ b/genlayer_py/consensus/abi/__init__.py @@ -1,37 +1,45 @@ import json import importlib.resources -with importlib.resources.as_file( - importlib.resources.files("genlayer_py.consensus.abi").joinpath( - "consensus_data_abi.json" - ) -) as path, open(path, "r", encoding="utf-8") as f: - CONSENSUS_DATA_ABI = json.load(f) -with importlib.resources.as_file( - importlib.resources.files("genlayer_py.consensus.abi").joinpath( - "consensus_main_abi.json" - ) -) as path, open(path, "r", encoding="utf-8") as f: - CONSENSUS_MAIN_ABI = json.load(f) +def _load_abi(name: str): + with ( + importlib.resources.as_file( + importlib.resources.files("genlayer_py.consensus.abi").joinpath(name) + ) as path, + open(path, "r", encoding="utf-8") as file, + ): + return json.load(file) -with importlib.resources.as_file( - importlib.resources.files("genlayer_py.consensus.abi").joinpath( - "consensus_data_abi_v06.json" - ) -) as path, open(path, "r", encoding="utf-8") as f: - CONSENSUS_DATA_ABI_V06 = json.load(f) -with importlib.resources.as_file( - importlib.resources.files("genlayer_py.consensus.abi").joinpath( - "consensus_main_abi_v06.json" - ) -) as path, open(path, "r", encoding="utf-8") as f: - CONSENSUS_MAIN_ABI_V06 = json.load(f) +CONSENSUS_DATA_LIFECYCLE_ABI = _load_abi("consensus_data_lifecycle_abi.json") +CONSENSUS_DATA_TRAIN_READS_ABI = _load_abi("consensus_data_train_reads_abi.json") +CONSENSUS_DATA_TRAIN_ABI = CONSENSUS_DATA_LIFECYCLE_ABI + CONSENSUS_DATA_TRAIN_READS_ABI +CONSENSUS_DATA_ABI = _load_abi("consensus_data_abi.json") +CONSENSUS_MAIN_ABI = _load_abi("consensus_main_abi.json") +APPEALS_ABI = _load_abi("appeals_abi.json") + +# Preserve the historical import names without preserving an old contract +# surface. This SDK release targets the train ABI only. +CONSENSUS_DATA_ABI_V06 = CONSENSUS_DATA_ABI +CONSENSUS_MAIN_ABI_V06 = CONSENSUS_MAIN_ABI + +CONSENSUS_DATA_BIG_ROUNDS_ABI = _load_abi("consensus_data_big_rounds_abi.json") +ADDRESS_MANAGER_ABI = _load_abi("address_manager_abi.json") +TRANSACTION_MANAGER_READ_ABI = _load_abi("transaction_manager_read_abi.json") +ROUNDS_STORAGE_READ_ABI = _load_abi("rounds_storage_read_abi.json") __all__ = [ "CONSENSUS_DATA_ABI", "CONSENSUS_MAIN_ABI", "CONSENSUS_DATA_ABI_V06", "CONSENSUS_MAIN_ABI_V06", + "APPEALS_ABI", + "CONSENSUS_DATA_LIFECYCLE_ABI", + "CONSENSUS_DATA_TRAIN_READS_ABI", + "CONSENSUS_DATA_TRAIN_ABI", + "CONSENSUS_DATA_BIG_ROUNDS_ABI", + "ADDRESS_MANAGER_ABI", + "TRANSACTION_MANAGER_READ_ABI", + "ROUNDS_STORAGE_READ_ABI", ] diff --git a/genlayer_py/consensus/abi/address_manager_abi.json b/genlayer_py/consensus/abi/address_manager_abi.json new file mode 100644 index 0000000..424b78f --- /dev/null +++ b/genlayer_py/consensus/abi/address_manager_abi.json @@ -0,0 +1,21 @@ +[ + { + "inputs": [ + { + "internalType": "string", + "name": "key", + "type": "string" + } + ], + "name": "getAddressNonZero", + "outputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/genlayer_py/consensus/abi/appeals_abi.json b/genlayer_py/consensus/abi/appeals_abi.json new file mode 100644 index 0000000..7e5f616 --- /dev/null +++ b/genlayer_py/consensus/abi/appeals_abi.json @@ -0,0 +1,710 @@ +[ + { + "inputs": [], + "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": [], + "name": "CanNotAppeal", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidAppealBond", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSender", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTransactionStatus", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "validators", + "type": "address[]" + } + ], + "name": "AppealCommitteeSelected", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + } + ], + "name": "AppealSelectionAborted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "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" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "round", + "type": "uint256" + } + ], + "name": "UnionRoundCreated", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "addressManager", + "outputs": [ + { + "internalType": "contract IAddressManager", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_expectedDecisionId", + "type": "uint256" + } + ], + "name": "canAppeal", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "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": "address", + "name": "_addressManager", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "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": "address", + "name": "_addressManager", + "type": "address" + } + ], + "name": "setAddressManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "enum ITransactions.ResultType", + "name": "result", + "type": "uint8" + }, + { + "internalType": "enum ITransactions.VoteType", + "name": "txExecutionResult", + "type": "uint8" + }, + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "status", + "type": "uint8" + }, + { + "internalType": "address", + "name": "txOrigin", + "type": "address" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "address", + "name": "activator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "txSlot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialRotations", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "numOfInitialValidators", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "randomSeed", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "txExecutionHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "resultHash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "txCalldata", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "eqBlocksOutputs", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "activationBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "processingBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "proposalBlock", + "type": "uint256" + } + ], + "internalType": "struct ITransactions.ReadStateBlockRange[]", + "name": "readStateBlockRanges", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "validUntil", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lockedStorageUnitPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "storageFeeUsed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lockedReceiptGasPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "txSigner", + "type": "address" + }, + { + "internalType": "enum ITransactions.QueueContext", + "name": "queueContext", + "type": "uint8" + } + ], + "internalType": "struct ITransactions.Transaction", + "name": "_transaction", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "_appealBond", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_expectedDecisionId", + "type": "uint256" + } + ], + "name": "submitAppeal", + "outputs": [ + { + "internalType": "address[]", + "name": "appealValidators", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "round", + "type": "uint256" + }, + { + "internalType": "address", + "name": "newLeader", + "type": "address" + }, + { + "internalType": "uint256", + "name": "leaderIndex", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "lastRoundLeaderTimeoutOrUndetermined", + "type": "bool" + }, + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "status", + "type": "uint8" + }, + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "previousStatus", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "appealBond", + "type": "uint256" + } + ], + "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": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/genlayer_py/consensus/abi/consensus_data_abi.json b/genlayer_py/consensus/abi/consensus_data_abi.json index ac30f82..ef27aa5 100644 --- a/genlayer_py/consensus/abi/consensus_data_abi.json +++ b/genlayer_py/consensus/abi/consensus_data_abi.json @@ -1,2577 +1,2573 @@ [ - { - "inputs": [], - "name": "AccessControlBadConfirmation", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "neededRole", - "type": "bytes32" - } - ], - "name": "AccessControlUnauthorizedAccount", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidInitialization", - "type": "error" - }, - { - "inputs": [], - "name": "NotInitializing", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "OwnableInvalidOwner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "OwnableUnauthorizedAccount", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrancyGuardReentrantCall", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "version", - "type": "uint64" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferStarted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "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": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_currentTimestamp", - "type": "uint256" - } - ], - "name": "canFinalize", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "consensusMain", - "outputs": [ - { - "internalType": "contract IConsensusMain", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_tx_id", - "type": "bytes32" - } - ], - "name": "getLastAppealResult", - "outputs": [ - { - "internalType": "enum ITransactions.ResultType", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "getLatestAcceptedTransaction", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "currentTimestamp", - "type": "uint256" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "numOfInitialValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "txSlot", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "createdTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lastVoteTimestamp", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "randomSeed", - "type": "bytes32" - }, - { - "internalType": "enum ITransactions.ResultType", - "name": "result", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "txData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "txReceipt", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "enum IMessages.MessageType", - "name": "messageType", - "type": "uint8" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "bool", - "name": "onAcceptance", - "type": "bool" - } - ], - "internalType": "struct IMessages.SubmittedMessage[]", - "name": "messages", - "type": "tuple[]" - }, - { - "internalType": "enum IQueues.QueueType", - "name": "queueType", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "queuePosition", - "type": "uint256" - }, - { - "internalType": "address", - "name": "activator", - "type": "address" - }, - { - "internalType": "address", - "name": "lastLeader", - "type": "address" - }, - { - "internalType": "enum ITransactions.TransactionStatus", - "name": "status", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "activationBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "processingBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "proposalBlock", - "type": "uint256" - } - ], - "internalType": "struct ITransactions.ReadStateBlockRange", - "name": "readStateBlockRange", - "type": "tuple" - }, - { - "internalType": "uint256", - "name": "numOfRounds", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "round", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "leaderIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "votesCommitted", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "votesRevealed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "appealBond", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "rotationsLeft", - "type": "uint256" - }, - { - "internalType": "enum ITransactions.ResultType", - "name": "result", - "type": "uint8" - }, - { - "internalType": "address[]", - "name": "roundValidators", - "type": "address[]" - }, - { - "internalType": "bytes32[]", - "name": "validatorVotesHash", - "type": "bytes32[]" - }, - { - "internalType": "enum ITransactions.VoteType[]", - "name": "validatorVotes", - "type": "uint8[]" - } - ], - "internalType": "struct ITransactions.RoundData", - "name": "lastRound", - "type": "tuple" - } - ], - "internalType": "struct ConsensusData.TransactionData", - "name": "txData", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "pageSize", - "type": "uint256" - } - ], - "name": "getLatestAcceptedTransactions", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "currentTimestamp", - "type": "uint256" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "numOfInitialValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "txSlot", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "createdTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lastVoteTimestamp", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "randomSeed", - "type": "bytes32" - }, - { - "internalType": "enum ITransactions.ResultType", - "name": "result", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "txData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "txReceipt", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "enum IMessages.MessageType", - "name": "messageType", - "type": "uint8" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "bool", - "name": "onAcceptance", - "type": "bool" - } - ], - "internalType": "struct IMessages.SubmittedMessage[]", - "name": "messages", - "type": "tuple[]" - }, - { - "internalType": "enum IQueues.QueueType", - "name": "queueType", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "queuePosition", - "type": "uint256" - }, - { - "internalType": "address", - "name": "activator", - "type": "address" - }, - { - "internalType": "address", - "name": "lastLeader", - "type": "address" - }, - { - "internalType": "enum ITransactions.TransactionStatus", - "name": "status", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "activationBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "processingBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "proposalBlock", - "type": "uint256" - } - ], - "internalType": "struct ITransactions.ReadStateBlockRange", - "name": "readStateBlockRange", - "type": "tuple" - }, - { - "internalType": "uint256", - "name": "numOfRounds", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "round", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "leaderIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "votesCommitted", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "votesRevealed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "appealBond", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "rotationsLeft", - "type": "uint256" - }, - { - "internalType": "enum ITransactions.ResultType", - "name": "result", - "type": "uint8" - }, - { - "internalType": "address[]", - "name": "roundValidators", - "type": "address[]" - }, - { - "internalType": "bytes32[]", - "name": "validatorVotesHash", - "type": "bytes32[]" - }, - { - "internalType": "enum ITransactions.VoteType[]", - "name": "validatorVotes", - "type": "uint8[]" - } - ], - "internalType": "struct ITransactions.RoundData", - "name": "lastRound", - "type": "tuple" - } - ], - "internalType": "struct ConsensusData.TransactionData[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "getLatestAcceptedTxCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "getLatestFinalizedTransaction", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "currentTimestamp", - "type": "uint256" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "numOfInitialValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "txSlot", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "createdTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lastVoteTimestamp", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "randomSeed", - "type": "bytes32" - }, - { - "internalType": "enum ITransactions.ResultType", - "name": "result", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "txData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "txReceipt", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "enum IMessages.MessageType", - "name": "messageType", - "type": "uint8" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "bool", - "name": "onAcceptance", - "type": "bool" - } - ], - "internalType": "struct IMessages.SubmittedMessage[]", - "name": "messages", - "type": "tuple[]" - }, - { - "internalType": "enum IQueues.QueueType", - "name": "queueType", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "queuePosition", - "type": "uint256" - }, - { - "internalType": "address", - "name": "activator", - "type": "address" - }, - { - "internalType": "address", - "name": "lastLeader", - "type": "address" - }, - { - "internalType": "enum ITransactions.TransactionStatus", - "name": "status", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "activationBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "processingBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "proposalBlock", - "type": "uint256" - } - ], - "internalType": "struct ITransactions.ReadStateBlockRange", - "name": "readStateBlockRange", - "type": "tuple" - }, - { - "internalType": "uint256", - "name": "numOfRounds", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "round", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "leaderIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "votesCommitted", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "votesRevealed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "appealBond", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "rotationsLeft", - "type": "uint256" - }, - { - "internalType": "enum ITransactions.ResultType", - "name": "result", - "type": "uint8" - }, - { - "internalType": "address[]", - "name": "roundValidators", - "type": "address[]" - }, - { - "internalType": "bytes32[]", - "name": "validatorVotesHash", - "type": "bytes32[]" - }, - { - "internalType": "enum ITransactions.VoteType[]", - "name": "validatorVotes", - "type": "uint8[]" - } - ], - "internalType": "struct ITransactions.RoundData", - "name": "lastRound", - "type": "tuple" - } - ], - "internalType": "struct ConsensusData.TransactionData", - "name": "txData", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "pageSize", - "type": "uint256" - } - ], - "name": "getLatestFinalizedTransactions", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "currentTimestamp", - "type": "uint256" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "numOfInitialValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "txSlot", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "createdTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lastVoteTimestamp", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "randomSeed", - "type": "bytes32" - }, - { - "internalType": "enum ITransactions.ResultType", - "name": "result", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "txData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "txReceipt", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "enum IMessages.MessageType", - "name": "messageType", - "type": "uint8" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "bool", - "name": "onAcceptance", - "type": "bool" - } - ], - "internalType": "struct IMessages.SubmittedMessage[]", - "name": "messages", - "type": "tuple[]" - }, - { - "internalType": "enum IQueues.QueueType", - "name": "queueType", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "queuePosition", - "type": "uint256" - }, - { - "internalType": "address", - "name": "activator", - "type": "address" - }, - { - "internalType": "address", - "name": "lastLeader", - "type": "address" - }, - { - "internalType": "enum ITransactions.TransactionStatus", - "name": "status", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "activationBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "processingBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "proposalBlock", - "type": "uint256" - } - ], - "internalType": "struct ITransactions.ReadStateBlockRange", - "name": "readStateBlockRange", - "type": "tuple" - }, - { - "internalType": "uint256", - "name": "numOfRounds", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "round", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "leaderIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "votesCommitted", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "votesRevealed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "appealBond", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "rotationsLeft", - "type": "uint256" - }, - { - "internalType": "enum ITransactions.ResultType", - "name": "result", - "type": "uint8" - }, - { - "internalType": "address[]", - "name": "roundValidators", - "type": "address[]" - }, - { - "internalType": "bytes32[]", - "name": "validatorVotesHash", - "type": "bytes32[]" - }, - { - "internalType": "enum ITransactions.VoteType[]", - "name": "validatorVotes", - "type": "uint8[]" - } - ], - "internalType": "struct ITransactions.RoundData", - "name": "lastRound", - "type": "tuple" - } - ], - "internalType": "struct ConsensusData.TransactionData[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "getLatestFinalizedTxCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "getLatestPendingTxCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "slot", - "type": "uint256" - } - ], - "name": "getLatestPendingTxId", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "getLatestUndeterminedTransaction", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "currentTimestamp", - "type": "uint256" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "numOfInitialValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "txSlot", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "createdTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lastVoteTimestamp", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "randomSeed", - "type": "bytes32" - }, - { - "internalType": "enum ITransactions.ResultType", - "name": "result", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "txData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "txReceipt", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "enum IMessages.MessageType", - "name": "messageType", - "type": "uint8" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "bool", - "name": "onAcceptance", - "type": "bool" - } - ], - "internalType": "struct IMessages.SubmittedMessage[]", - "name": "messages", - "type": "tuple[]" - }, - { - "internalType": "enum IQueues.QueueType", - "name": "queueType", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "queuePosition", - "type": "uint256" - }, - { - "internalType": "address", - "name": "activator", - "type": "address" - }, - { - "internalType": "address", - "name": "lastLeader", - "type": "address" - }, - { - "internalType": "enum ITransactions.TransactionStatus", - "name": "status", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "activationBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "processingBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "proposalBlock", - "type": "uint256" - } - ], - "internalType": "struct ITransactions.ReadStateBlockRange", - "name": "readStateBlockRange", - "type": "tuple" - }, - { - "internalType": "uint256", - "name": "numOfRounds", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "round", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "leaderIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "votesCommitted", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "votesRevealed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "appealBond", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "rotationsLeft", - "type": "uint256" - }, - { - "internalType": "enum ITransactions.ResultType", - "name": "result", - "type": "uint8" - }, - { - "internalType": "address[]", - "name": "roundValidators", - "type": "address[]" - }, - { - "internalType": "bytes32[]", - "name": "validatorVotesHash", - "type": "bytes32[]" - }, - { - "internalType": "enum ITransactions.VoteType[]", - "name": "validatorVotes", - "type": "uint8[]" - } - ], - "internalType": "struct ITransactions.RoundData", - "name": "lastRound", - "type": "tuple" - } - ], - "internalType": "struct ConsensusData.TransactionData", - "name": "txData", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "getLatestUndeterminedTxCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_tx_id", - "type": "bytes32" - } - ], - "name": "getMessagesForTransaction", - "outputs": [ - { - "components": [ - { - "internalType": "enum IMessages.MessageType", - "name": "messageType", - "type": "uint8" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "bool", - "name": "onAcceptance", - "type": "bool" - } - ], - "internalType": "struct IMessages.SubmittedMessage[]", - "name": "", - "type": "tuple[]" - }, - { - "internalType": "address", - "name": "ghostAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "numOfMessagesIssuedOnAcceptance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "numOfMessagesIssuedOnFinalization", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_tx_id", - "type": "bytes32" - } - ], - "name": "getReadStateBlockRangeForTransaction", - "outputs": [ - { - "internalType": "uint256", - "name": "activationBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "processingBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "proposalBlock", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "endIndex", - "type": "uint256" - } - ], - "name": "getRecipientQueues", - "outputs": [ - { - "components": [ - { - "components": [ - { - "internalType": "uint256", - "name": "head", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "tail", - "type": "uint256" - }, - { - "internalType": "bytes32[]", - "name": "txIds", - "type": "bytes32[]" - } - ], - "internalType": "struct IQueues.QueueInfoView", - "name": "pending", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "head", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "tail", - "type": "uint256" - }, - { - "internalType": "bytes32[]", - "name": "txIds", - "type": "bytes32[]" - } - ], - "internalType": "struct IQueues.QueueInfoView", - "name": "accepted", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "head", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "tail", - "type": "uint256" - }, - { - "internalType": "bytes32[]", - "name": "txIds", - "type": "bytes32[]" - } - ], - "internalType": "struct IQueues.QueueInfoView", - "name": "undetermined", - "type": "tuple" - }, - { - "internalType": "uint256", - "name": "finalizedCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "issuedTxCount", - "type": "uint256" - } - ], - "internalType": "struct IQueues.RecipientQueuesView", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - } - ], - "name": "getRoleAdmin", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getTotalNumOfTransactions", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_tx_id", - "type": "bytes32" - } - ], - "name": "getTransactionAllData", - "outputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "numOfInitialValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "txSlot", - "type": "uint256" - }, - { - "internalType": "address", - "name": "activator", - "type": "address" - }, - { - "internalType": "enum ITransactions.TransactionStatus", - "name": "status", - "type": "uint8" - }, - { - "internalType": "enum ITransactions.TransactionStatus", - "name": "previousStatus", - "type": "uint8" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "created", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "pending", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "activated", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "proposed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "committed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lastVote", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "appealSubmitted", - "type": "uint256" - } - ], - "internalType": "struct ITransactions.Timestamps", - "name": "timestamps", - "type": "tuple" - }, - { - "internalType": "bytes32", - "name": "randomSeed", - "type": "bytes32" - }, - { - "internalType": "bool", - "name": "onAcceptanceMessages", - "type": "bool" - }, - { - "internalType": "enum ITransactions.ResultType", - "name": "result", - "type": "uint8" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "activationBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "processingBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "proposalBlock", - "type": "uint256" - } - ], - "internalType": "struct ITransactions.ReadStateBlockRange", - "name": "readStateBlockRange", - "type": "tuple" - }, - { - "internalType": "bytes", - "name": "txData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "txReceipt", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "enum IMessages.MessageType", - "name": "messageType", - "type": "uint8" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "bool", - "name": "onAcceptance", - "type": "bool" - } - ], - "internalType": "struct IMessages.SubmittedMessage[]", - "name": "messages", - "type": "tuple[]" - }, - { - "internalType": "address[]", - "name": "consumedValidators", - "type": "address[]" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "round", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "leaderIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "votesCommitted", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "votesRevealed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "appealBond", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "rotationsLeft", - "type": "uint256" - }, - { - "internalType": "enum ITransactions.ResultType", - "name": "result", - "type": "uint8" - }, - { - "internalType": "address[]", - "name": "roundValidators", - "type": "address[]" - }, - { - "internalType": "bytes32[]", - "name": "validatorVotesHash", - "type": "bytes32[]" - }, - { - "internalType": "enum ITransactions.VoteType[]", - "name": "validatorVotes", - "type": "uint8[]" - } - ], - "internalType": "struct ITransactions.RoundData[]", - "name": "roundData", - "type": "tuple[]" - }, - { - "internalType": "uint256", - "name": "numOfMessagesIssuedOnAcceptance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "numOfMessagesIssuedOnFinalization", - "type": "uint256" - }, - { - "internalType": "address", - "name": "txOrigin", - "type": "address" - }, - { - "internalType": "uint256", - "name": "initialRotations", - "type": "uint256" - } - ], - "internalType": "struct ITransactions.Transaction", - "name": "transaction", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_tx_id", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_timestamp", - "type": "uint256" - } - ], - "name": "getTransactionData", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "currentTimestamp", - "type": "uint256" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "numOfInitialValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "txSlot", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "createdTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lastVoteTimestamp", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "randomSeed", - "type": "bytes32" - }, - { - "internalType": "enum ITransactions.ResultType", - "name": "result", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "txData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "txReceipt", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "enum IMessages.MessageType", - "name": "messageType", - "type": "uint8" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "bool", - "name": "onAcceptance", - "type": "bool" - } - ], - "internalType": "struct IMessages.SubmittedMessage[]", - "name": "messages", - "type": "tuple[]" - }, - { - "internalType": "enum IQueues.QueueType", - "name": "queueType", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "queuePosition", - "type": "uint256" - }, - { - "internalType": "address", - "name": "activator", - "type": "address" - }, - { - "internalType": "address", - "name": "lastLeader", - "type": "address" - }, - { - "internalType": "enum ITransactions.TransactionStatus", - "name": "status", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "activationBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "processingBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "proposalBlock", - "type": "uint256" - } - ], - "internalType": "struct ITransactions.ReadStateBlockRange", - "name": "readStateBlockRange", - "type": "tuple" - }, - { - "internalType": "uint256", - "name": "numOfRounds", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "round", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "leaderIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "votesCommitted", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "votesRevealed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "appealBond", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "rotationsLeft", - "type": "uint256" - }, - { - "internalType": "enum ITransactions.ResultType", - "name": "result", - "type": "uint8" - }, - { - "internalType": "address[]", - "name": "roundValidators", - "type": "address[]" - }, - { - "internalType": "bytes32[]", - "name": "validatorVotesHash", - "type": "bytes32[]" - }, - { - "internalType": "enum ITransactions.VoteType[]", - "name": "validatorVotes", - "type": "uint8[]" - } - ], - "internalType": "struct ITransactions.RoundData", - "name": "lastRound", - "type": "tuple" - } - ], - "internalType": "struct ConsensusData.TransactionData", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "endIndex", - "type": "uint256" - } - ], - "name": "getTransactionIndexToTxId", - "outputs": [ - { - "internalType": "bytes32[]", - "name": "", - "type": "bytes32[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_tx_id", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_timestamp", - "type": "uint256" - } - ], - "name": "getTransactionStatus", - "outputs": [ - { - "internalType": "enum ITransactions.TransactionStatus", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_tx_id", - "type": "bytes32" - } - ], - "name": "getValidatorsForLastAppeal", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_tx_id", - "type": "bytes32" - } - ], - "name": "getValidatorsForLastRound", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "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": "bytes32", - "name": "_tx_id", - "type": "bytes32" - } - ], - "name": "hasTransactionOnAcceptanceMessages", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_tx_id", - "type": "bytes32" - } - ], - "name": "hasTransactionOnFinalizationMessages", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_consensusMain", - "type": "address" - }, - { - "internalType": "address", - "name": "_transactions", - "type": "address" - }, - { - "internalType": "address", - "name": "_queues", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pendingOwner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "queues", - "outputs": [ - { - "internalType": "contract IQueues", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "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": "address", - "name": "_consensusMain", - "type": "address" - } - ], - "name": "setConsensusMain", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_queues", - "type": "address" - } - ], - "name": "setQueues", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_transactions", - "type": "address" - } - ], - "name": "setTransactions", - "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": [], - "name": "transactions", - "outputs": [ - { - "internalType": "contract ITransactions", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] \ No newline at end of file + { + "inputs": [], + "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": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTransactionStatus", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "status", + "type": "uint8" + } + ], + "name": "PhaseDeadlineNotInitialized", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrancyGuardReentrantCall", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "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": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "addressManager", + "outputs": [ + { + "internalType": "contract IAddressManager", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_currentTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_expectedDecisionId", + "type": "uint256" + } + ], + "name": "canFinalize", + "outputs": [ + { + "internalType": "bool", + "name": "ready", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "evaluatedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "appealDeadline", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + } + ], + "name": "estimateAppealBond", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + } + ], + "name": "estimateLatestAppealCharge", + "outputs": [ + { + "internalType": "uint256", + "name": "decisionId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "bond", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "funding", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "appealDeadline", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + } + ], + "name": "getCurrentActivator", + "outputs": [ + { + "internalType": "address", + "name": "newActivator", + "type": "address" + }, + { + "internalType": "bool", + "name": "activatorIsIdle", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "slots", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "secondsUntilNextBoundary", + "type": "uint256" + }, + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "currentStatus", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + } + ], + "name": "getCurrentLeader", + "outputs": [ + { + "internalType": "address", + "name": "newLeader", + "type": "address" + }, + { + "internalType": "bool", + "name": "leaderIsIdle", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "slots", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "secondsUntilNextBoundary", + "type": "uint256" + }, + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "currentStatus", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + } + ], + "name": "getCurrentValidators", + "outputs": [ + { + "internalType": "address[]", + "name": "validators", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "leaderIndex", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "idleIndexes", + "type": "uint256[]" + }, + { + "internalType": "bool", + "name": "leaderIsIdle", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "slots", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "secondsUntilNextBoundary", + "type": "uint256" + }, + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "currentStatus", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "getLatestAcceptedTransaction", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "observedAt", + "type": "uint256" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialRotations", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "txSlot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "createdTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lastVoteTimestamp", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "randomSeed", + "type": "bytes32" + }, + { + "internalType": "enum ITransactions.ResultType", + "name": "result", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "txExecutionHash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "txCalldata", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "eqBlocksOutputs", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "enum IMessages.MessageType", + "name": "messageType", + "type": "uint8" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "onAcceptance", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "saltNonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "feeParams", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "declaredBudget", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "allocationSubtree", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "callKey", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "useBalance", + "type": "bool" + } + ], + "internalType": "struct IMessages.SubmittedMessage[]", + "name": "messages", + "type": "tuple[]" + }, + { + "internalType": "enum IQueues.QueueType", + "name": "queueType", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "queuePosition", + "type": "uint256" + }, + { + "internalType": "address", + "name": "activator", + "type": "address" + }, + { + "internalType": "address", + "name": "lastLeader", + "type": "address" + }, + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "status", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "activationBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "processingBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "proposalBlock", + "type": "uint256" + } + ], + "internalType": "struct ITransactions.ReadStateBlockRange", + "name": "readStateBlockRange", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "numOfRounds", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "round", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "leaderIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "votesCommitted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "votesRevealed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "appealBond", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rotationsLeft", + "type": "uint256" + }, + { + "internalType": "enum ITransactions.ResultType", + "name": "result", + "type": "uint8" + }, + { + "internalType": "address[]", + "name": "roundValidators", + "type": "address[]" + }, + { + "internalType": "enum ITransactions.VoteType[]", + "name": "validatorVotes", + "type": "uint8[]" + }, + { + "internalType": "bytes32[]", + "name": "validatorVotesHash", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "validatorResultHash", + "type": "bytes32[]" + } + ], + "internalType": "struct ITransactions.RoundData", + "name": "lastRound", + "type": "tuple" + }, + { + "internalType": "address[]", + "name": "consumedValidators", + "type": "address[]" + } + ], + "internalType": "struct ConsensusData.TransactionData", + "name": "inputData", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "pageSize", + "type": "uint256" + } + ], + "name": "getLatestAcceptedTransactions", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "observedAt", + "type": "uint256" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialRotations", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "txSlot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "createdTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lastVoteTimestamp", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "randomSeed", + "type": "bytes32" + }, + { + "internalType": "enum ITransactions.ResultType", + "name": "result", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "txExecutionHash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "txCalldata", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "eqBlocksOutputs", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "enum IMessages.MessageType", + "name": "messageType", + "type": "uint8" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "onAcceptance", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "saltNonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "feeParams", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "declaredBudget", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "allocationSubtree", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "callKey", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "useBalance", + "type": "bool" + } + ], + "internalType": "struct IMessages.SubmittedMessage[]", + "name": "messages", + "type": "tuple[]" + }, + { + "internalType": "enum IQueues.QueueType", + "name": "queueType", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "queuePosition", + "type": "uint256" + }, + { + "internalType": "address", + "name": "activator", + "type": "address" + }, + { + "internalType": "address", + "name": "lastLeader", + "type": "address" + }, + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "status", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "activationBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "processingBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "proposalBlock", + "type": "uint256" + } + ], + "internalType": "struct ITransactions.ReadStateBlockRange", + "name": "readStateBlockRange", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "numOfRounds", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "round", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "leaderIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "votesCommitted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "votesRevealed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "appealBond", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rotationsLeft", + "type": "uint256" + }, + { + "internalType": "enum ITransactions.ResultType", + "name": "result", + "type": "uint8" + }, + { + "internalType": "address[]", + "name": "roundValidators", + "type": "address[]" + }, + { + "internalType": "enum ITransactions.VoteType[]", + "name": "validatorVotes", + "type": "uint8[]" + }, + { + "internalType": "bytes32[]", + "name": "validatorVotesHash", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "validatorResultHash", + "type": "bytes32[]" + } + ], + "internalType": "struct ITransactions.RoundData", + "name": "lastRound", + "type": "tuple" + }, + { + "internalType": "address[]", + "name": "consumedValidators", + "type": "address[]" + } + ], + "internalType": "struct ConsensusData.TransactionData[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "getLatestAcceptedTxCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "getLatestFinalizedTransaction", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "observedAt", + "type": "uint256" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialRotations", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "txSlot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "createdTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lastVoteTimestamp", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "randomSeed", + "type": "bytes32" + }, + { + "internalType": "enum ITransactions.ResultType", + "name": "result", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "txExecutionHash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "txCalldata", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "eqBlocksOutputs", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "enum IMessages.MessageType", + "name": "messageType", + "type": "uint8" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "onAcceptance", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "saltNonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "feeParams", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "declaredBudget", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "allocationSubtree", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "callKey", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "useBalance", + "type": "bool" + } + ], + "internalType": "struct IMessages.SubmittedMessage[]", + "name": "messages", + "type": "tuple[]" + }, + { + "internalType": "enum IQueues.QueueType", + "name": "queueType", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "queuePosition", + "type": "uint256" + }, + { + "internalType": "address", + "name": "activator", + "type": "address" + }, + { + "internalType": "address", + "name": "lastLeader", + "type": "address" + }, + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "status", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "activationBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "processingBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "proposalBlock", + "type": "uint256" + } + ], + "internalType": "struct ITransactions.ReadStateBlockRange", + "name": "readStateBlockRange", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "numOfRounds", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "round", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "leaderIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "votesCommitted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "votesRevealed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "appealBond", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rotationsLeft", + "type": "uint256" + }, + { + "internalType": "enum ITransactions.ResultType", + "name": "result", + "type": "uint8" + }, + { + "internalType": "address[]", + "name": "roundValidators", + "type": "address[]" + }, + { + "internalType": "enum ITransactions.VoteType[]", + "name": "validatorVotes", + "type": "uint8[]" + }, + { + "internalType": "bytes32[]", + "name": "validatorVotesHash", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "validatorResultHash", + "type": "bytes32[]" + } + ], + "internalType": "struct ITransactions.RoundData", + "name": "lastRound", + "type": "tuple" + }, + { + "internalType": "address[]", + "name": "consumedValidators", + "type": "address[]" + } + ], + "internalType": "struct ConsensusData.TransactionData", + "name": "inputData", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "pageSize", + "type": "uint256" + } + ], + "name": "getLatestFinalizedTransactions", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "observedAt", + "type": "uint256" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialRotations", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "txSlot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "createdTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lastVoteTimestamp", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "randomSeed", + "type": "bytes32" + }, + { + "internalType": "enum ITransactions.ResultType", + "name": "result", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "txExecutionHash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "txCalldata", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "eqBlocksOutputs", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "enum IMessages.MessageType", + "name": "messageType", + "type": "uint8" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "onAcceptance", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "saltNonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "feeParams", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "declaredBudget", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "allocationSubtree", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "callKey", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "useBalance", + "type": "bool" + } + ], + "internalType": "struct IMessages.SubmittedMessage[]", + "name": "messages", + "type": "tuple[]" + }, + { + "internalType": "enum IQueues.QueueType", + "name": "queueType", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "queuePosition", + "type": "uint256" + }, + { + "internalType": "address", + "name": "activator", + "type": "address" + }, + { + "internalType": "address", + "name": "lastLeader", + "type": "address" + }, + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "status", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "activationBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "processingBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "proposalBlock", + "type": "uint256" + } + ], + "internalType": "struct ITransactions.ReadStateBlockRange", + "name": "readStateBlockRange", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "numOfRounds", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "round", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "leaderIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "votesCommitted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "votesRevealed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "appealBond", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rotationsLeft", + "type": "uint256" + }, + { + "internalType": "enum ITransactions.ResultType", + "name": "result", + "type": "uint8" + }, + { + "internalType": "address[]", + "name": "roundValidators", + "type": "address[]" + }, + { + "internalType": "enum ITransactions.VoteType[]", + "name": "validatorVotes", + "type": "uint8[]" + }, + { + "internalType": "bytes32[]", + "name": "validatorVotesHash", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "validatorResultHash", + "type": "bytes32[]" + } + ], + "internalType": "struct ITransactions.RoundData", + "name": "lastRound", + "type": "tuple" + }, + { + "internalType": "address[]", + "name": "consumedValidators", + "type": "address[]" + } + ], + "internalType": "struct ConsensusData.TransactionData[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "getLatestFinalizedTxCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "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": "_txId", + "type": "bytes32" + } + ], + "name": "getStoredTransactionData", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "observedAt", + "type": "uint256" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialRotations", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "txSlot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "createdTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lastVoteTimestamp", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "randomSeed", + "type": "bytes32" + }, + { + "internalType": "enum ITransactions.ResultType", + "name": "result", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "txExecutionHash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "txCalldata", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "eqBlocksOutputs", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "enum IMessages.MessageType", + "name": "messageType", + "type": "uint8" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "onAcceptance", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "saltNonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "feeParams", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "declaredBudget", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "allocationSubtree", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "callKey", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "useBalance", + "type": "bool" + } + ], + "internalType": "struct IMessages.SubmittedMessage[]", + "name": "messages", + "type": "tuple[]" + }, + { + "internalType": "enum IQueues.QueueType", + "name": "queueType", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "queuePosition", + "type": "uint256" + }, + { + "internalType": "address", + "name": "activator", + "type": "address" + }, + { + "internalType": "address", + "name": "lastLeader", + "type": "address" + }, + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "status", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "activationBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "processingBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "proposalBlock", + "type": "uint256" + } + ], + "internalType": "struct ITransactions.ReadStateBlockRange", + "name": "readStateBlockRange", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "numOfRounds", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "round", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "leaderIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "votesCommitted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "votesRevealed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "appealBond", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rotationsLeft", + "type": "uint256" + }, + { + "internalType": "enum ITransactions.ResultType", + "name": "result", + "type": "uint8" + }, + { + "internalType": "address[]", + "name": "roundValidators", + "type": "address[]" + }, + { + "internalType": "enum ITransactions.VoteType[]", + "name": "validatorVotes", + "type": "uint8[]" + }, + { + "internalType": "bytes32[]", + "name": "validatorVotesHash", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "validatorResultHash", + "type": "bytes32[]" + } + ], + "internalType": "struct ITransactions.RoundData", + "name": "lastRound", + "type": "tuple" + }, + { + "internalType": "address[]", + "name": "consumedValidators", + "type": "address[]" + } + ], + "internalType": "struct ConsensusData.TransactionData", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + } + ], + "name": "getStoredTransactionStatus", + "outputs": [ + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + } + ], + "name": "getTransactionAllData", + "outputs": [ + { + "components": [ + { + "internalType": "enum ITransactions.ResultType", + "name": "result", + "type": "uint8" + }, + { + "internalType": "enum ITransactions.VoteType", + "name": "txExecutionResult", + "type": "uint8" + }, + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "status", + "type": "uint8" + }, + { + "internalType": "address", + "name": "txOrigin", + "type": "address" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "address", + "name": "activator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "txSlot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialRotations", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "numOfInitialValidators", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "randomSeed", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "txExecutionHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "resultHash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "txCalldata", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "eqBlocksOutputs", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "activationBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "processingBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "proposalBlock", + "type": "uint256" + } + ], + "internalType": "struct ITransactions.ReadStateBlockRange[]", + "name": "readStateBlockRanges", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "validUntil", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lockedStorageUnitPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "storageFeeUsed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lockedReceiptGasPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "txSigner", + "type": "address" + }, + { + "internalType": "enum ITransactions.QueueContext", + "name": "queueContext", + "type": "uint8" + } + ], + "internalType": "struct ITransactions.Transaction", + "name": "transaction", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "round", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "leaderIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "votesCommitted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "votesRevealed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "appealBond", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rotationsLeft", + "type": "uint256" + }, + { + "internalType": "enum ITransactions.ResultType", + "name": "result", + "type": "uint8" + }, + { + "internalType": "address[]", + "name": "roundValidators", + "type": "address[]" + }, + { + "internalType": "enum ITransactions.VoteType[]", + "name": "validatorVotes", + "type": "uint8[]" + }, + { + "internalType": "bytes32[]", + "name": "validatorVotesHash", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "validatorResultHash", + "type": "bytes32[]" + } + ], + "internalType": "struct ITransactions.RoundData[]", + "name": "roundsData", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_timestamp", + "type": "uint256" + } + ], + "name": "getTransactionLifecycle", + "outputs": [ + { + "components": [ + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "storedStatus", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "storedStatus", + "type": "uint8" + }, + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "projectedStatus", + "type": "uint8" + }, + { + "internalType": "enum IIdlenessPhase.ResolutionAction", + "name": "action", + "type": "uint8" + }, + { + "internalType": "enum ITransactions.ResultType", + "name": "result", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "resultHash", + "type": "bytes32" + }, + { + "internalType": "enum ITransactionManager.ResolutionSource", + "name": "source", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "sourceRound", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sourceGeneration", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "sourceRoundContextHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "roundPlanHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "resultRound", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "resultGeneration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "basisDecisionId", + "type": "uint256" + }, + { + "internalType": "enum ITransactionManager.ResolutionContext", + "name": "context", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "attemptId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "boundaryAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "evaluatedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "snapshotBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "decisionWindow", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "appealDeadline", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "materializesDecision", + "type": "bool" + }, + { + "internalType": "bool", + "name": "actionOutcomeDeterministic", + "type": "bool" + }, + { + "internalType": "bool", + "name": "nonCurrentEvaluation", + "type": "bool" + } + ], + "internalType": "struct IIdlenessPhase.ResolutionPlan", + "name": "resolution", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "decisionId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "basisDecisionId", + "type": "uint256" + }, + { + "internalType": "enum ITransactionManager.ResolutionContext", + "name": "context", + "type": "uint8" + }, + { + "internalType": "enum ITransactionManager.ResolutionSource", + "name": "source", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "sourceAttemptId", + "type": "bytes32" + }, + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "sourceStatus", + "type": "uint8" + }, + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "status", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "sourceRound", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sourceGeneration", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "sourceRoundContextHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "roundPlanHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "resultRound", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "resultGeneration", + "type": "uint256" + }, + { + "internalType": "enum ITransactions.ResultType", + "name": "result", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "resultHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "effectiveAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "materializedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "appealDeadline", + "type": "uint256" + } + ], + "internalType": "struct ITransactionManager.DecisionRecord", + "name": "latestDecision", + "type": "tuple" + }, + { + "internalType": "bool", + "name": "decisionActive", + "type": "bool" + } + ], + "internalType": "struct ConsensusData.TransactionLifecycle", + "name": "lifecycle", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + } + ], + "name": "getValidatorsForLastRound", + "outputs": [ + { + "internalType": "address[]", + "name": "validators", + "type": "address[]" + } + ], + "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": "address", + "name": "_addressManager", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "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": "address", + "name": "_addressManager", + "type": "address" + } + ], + "name": "setAddressManager", + "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": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/genlayer_py/consensus/abi/consensus_data_abi_v06.json b/genlayer_py/consensus/abi/consensus_data_abi_v06.json index 60a382a..ef27aa5 100644 --- a/genlayer_py/consensus/abi/consensus_data_abi_v06.json +++ b/genlayer_py/consensus/abi/consensus_data_abi_v06.json @@ -1,1962 +1,2573 @@ [ - { - "inputs": [], - "name": "AccessControlBadConfirmation", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "neededRole", - "type": "bytes32" - } - ], - "name": "AccessControlUnauthorizedAccount", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidInitialization", - "type": "error" - }, - { - "inputs": [], - "name": "NotInitializing", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "OwnableInvalidOwner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "OwnableUnauthorizedAccount", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrancyGuardReentrantCall", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "version", - "type": "uint64" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferStarted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "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": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "addressManager", - "outputs": [ - { - "internalType": "contract IAddressManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_currentTimestamp", - "type": "uint256" - } - ], - "name": "canFinalize", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "getLatestAcceptedTransaction", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "currentTimestamp", - "type": "uint256" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "initialRotations", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "txSlot", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "createdTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lastVoteTimestamp", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "randomSeed", - "type": "bytes32" - }, - { - "internalType": "enum ITransactions.ResultType", - "name": "result", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "txExecutionHash", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "txCalldata", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "eqBlocksOutputs", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "enum IMessages.MessageType", - "name": "messageType", - "type": "uint8" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "bool", - "name": "onAcceptance", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "saltNonce", - "type": "uint256" - } - ], - "internalType": "struct IMessages.SubmittedMessage[]", - "name": "messages", - "type": "tuple[]" - }, - { - "internalType": "enum IQueues.QueueType", - "name": "queueType", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "queuePosition", - "type": "uint256" - }, - { - "internalType": "address", - "name": "activator", - "type": "address" - }, - { - "internalType": "address", - "name": "lastLeader", - "type": "address" - }, - { - "internalType": "enum ITransactions.TransactionStatus", - "name": "status", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "activationBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "processingBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "proposalBlock", - "type": "uint256" - } - ], - "internalType": "struct ITransactions.ReadStateBlockRange", - "name": "readStateBlockRange", - "type": "tuple" - }, - { - "internalType": "uint256", - "name": "numOfRounds", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "round", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "leaderIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "votesCommitted", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "votesRevealed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "appealBond", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "rotationsLeft", - "type": "uint256" - }, - { - "internalType": "enum ITransactions.ResultType", - "name": "result", - "type": "uint8" - }, - { - "internalType": "address[]", - "name": "roundValidators", - "type": "address[]" - }, - { - "internalType": "enum ITransactions.VoteType[]", - "name": "validatorVotes", - "type": "uint8[]" - }, - { - "internalType": "bytes32[]", - "name": "validatorVotesHash", - "type": "bytes32[]" - }, - { - "internalType": "bytes32[]", - "name": "validatorResultHash", - "type": "bytes32[]" - } - ], - "internalType": "struct ITransactions.RoundData", - "name": "lastRound", - "type": "tuple" - }, - { - "internalType": "address[]", - "name": "consumedValidators", - "type": "address[]" - } - ], - "internalType": "struct ConsensusData.TransactionData", - "name": "inputData", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "pageSize", - "type": "uint256" - } - ], - "name": "getLatestAcceptedTransactions", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "currentTimestamp", - "type": "uint256" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "initialRotations", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "txSlot", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "createdTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lastVoteTimestamp", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "randomSeed", - "type": "bytes32" - }, - { - "internalType": "enum ITransactions.ResultType", - "name": "result", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "txExecutionHash", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "txCalldata", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "eqBlocksOutputs", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "enum IMessages.MessageType", - "name": "messageType", - "type": "uint8" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "bool", - "name": "onAcceptance", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "saltNonce", - "type": "uint256" - } - ], - "internalType": "struct IMessages.SubmittedMessage[]", - "name": "messages", - "type": "tuple[]" - }, - { - "internalType": "enum IQueues.QueueType", - "name": "queueType", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "queuePosition", - "type": "uint256" - }, - { - "internalType": "address", - "name": "activator", - "type": "address" - }, - { - "internalType": "address", - "name": "lastLeader", - "type": "address" - }, - { - "internalType": "enum ITransactions.TransactionStatus", - "name": "status", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "activationBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "processingBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "proposalBlock", - "type": "uint256" - } - ], - "internalType": "struct ITransactions.ReadStateBlockRange", - "name": "readStateBlockRange", - "type": "tuple" - }, - { - "internalType": "uint256", - "name": "numOfRounds", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "round", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "leaderIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "votesCommitted", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "votesRevealed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "appealBond", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "rotationsLeft", - "type": "uint256" - }, - { - "internalType": "enum ITransactions.ResultType", - "name": "result", - "type": "uint8" - }, - { - "internalType": "address[]", - "name": "roundValidators", - "type": "address[]" - }, - { - "internalType": "enum ITransactions.VoteType[]", - "name": "validatorVotes", - "type": "uint8[]" - }, - { - "internalType": "bytes32[]", - "name": "validatorVotesHash", - "type": "bytes32[]" - }, - { - "internalType": "bytes32[]", - "name": "validatorResultHash", - "type": "bytes32[]" - } - ], - "internalType": "struct ITransactions.RoundData", - "name": "lastRound", - "type": "tuple" - }, - { - "internalType": "address[]", - "name": "consumedValidators", - "type": "address[]" - } - ], - "internalType": "struct ConsensusData.TransactionData[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "getLatestAcceptedTxCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "getLatestFinalizedTransaction", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "currentTimestamp", - "type": "uint256" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "initialRotations", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "txSlot", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "createdTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lastVoteTimestamp", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "randomSeed", - "type": "bytes32" - }, - { - "internalType": "enum ITransactions.ResultType", - "name": "result", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "txExecutionHash", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "txCalldata", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "eqBlocksOutputs", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "enum IMessages.MessageType", - "name": "messageType", - "type": "uint8" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "bool", - "name": "onAcceptance", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "saltNonce", - "type": "uint256" - } - ], - "internalType": "struct IMessages.SubmittedMessage[]", - "name": "messages", - "type": "tuple[]" - }, - { - "internalType": "enum IQueues.QueueType", - "name": "queueType", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "queuePosition", - "type": "uint256" - }, - { - "internalType": "address", - "name": "activator", - "type": "address" - }, - { - "internalType": "address", - "name": "lastLeader", - "type": "address" - }, - { - "internalType": "enum ITransactions.TransactionStatus", - "name": "status", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "activationBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "processingBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "proposalBlock", - "type": "uint256" - } - ], - "internalType": "struct ITransactions.ReadStateBlockRange", - "name": "readStateBlockRange", - "type": "tuple" - }, - { - "internalType": "uint256", - "name": "numOfRounds", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "round", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "leaderIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "votesCommitted", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "votesRevealed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "appealBond", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "rotationsLeft", - "type": "uint256" - }, - { - "internalType": "enum ITransactions.ResultType", - "name": "result", - "type": "uint8" - }, - { - "internalType": "address[]", - "name": "roundValidators", - "type": "address[]" - }, - { - "internalType": "enum ITransactions.VoteType[]", - "name": "validatorVotes", - "type": "uint8[]" - }, - { - "internalType": "bytes32[]", - "name": "validatorVotesHash", - "type": "bytes32[]" - }, - { - "internalType": "bytes32[]", - "name": "validatorResultHash", - "type": "bytes32[]" - } - ], - "internalType": "struct ITransactions.RoundData", - "name": "lastRound", - "type": "tuple" - }, - { - "internalType": "address[]", - "name": "consumedValidators", - "type": "address[]" - } - ], - "internalType": "struct ConsensusData.TransactionData", - "name": "inputData", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "pageSize", - "type": "uint256" - } - ], - "name": "getLatestFinalizedTransactions", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "currentTimestamp", - "type": "uint256" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "initialRotations", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "txSlot", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "createdTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lastVoteTimestamp", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "randomSeed", - "type": "bytes32" - }, - { - "internalType": "enum ITransactions.ResultType", - "name": "result", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "txExecutionHash", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "txCalldata", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "eqBlocksOutputs", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "enum IMessages.MessageType", - "name": "messageType", - "type": "uint8" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "bool", - "name": "onAcceptance", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "saltNonce", - "type": "uint256" - } - ], - "internalType": "struct IMessages.SubmittedMessage[]", - "name": "messages", - "type": "tuple[]" - }, - { - "internalType": "enum IQueues.QueueType", - "name": "queueType", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "queuePosition", - "type": "uint256" - }, - { - "internalType": "address", - "name": "activator", - "type": "address" - }, - { - "internalType": "address", - "name": "lastLeader", - "type": "address" - }, - { - "internalType": "enum ITransactions.TransactionStatus", - "name": "status", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "activationBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "processingBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "proposalBlock", - "type": "uint256" - } - ], - "internalType": "struct ITransactions.ReadStateBlockRange", - "name": "readStateBlockRange", - "type": "tuple" - }, - { - "internalType": "uint256", - "name": "numOfRounds", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "round", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "leaderIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "votesCommitted", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "votesRevealed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "appealBond", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "rotationsLeft", - "type": "uint256" - }, - { - "internalType": "enum ITransactions.ResultType", - "name": "result", - "type": "uint8" - }, - { - "internalType": "address[]", - "name": "roundValidators", - "type": "address[]" - }, - { - "internalType": "enum ITransactions.VoteType[]", - "name": "validatorVotes", - "type": "uint8[]" - }, - { - "internalType": "bytes32[]", - "name": "validatorVotesHash", - "type": "bytes32[]" - }, - { - "internalType": "bytes32[]", - "name": "validatorResultHash", - "type": "bytes32[]" - } - ], - "internalType": "struct ITransactions.RoundData", - "name": "lastRound", - "type": "tuple" - }, - { - "internalType": "address[]", - "name": "consumedValidators", - "type": "address[]" - } - ], - "internalType": "struct ConsensusData.TransactionData[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "getLatestFinalizedTxCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "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": "_txId", - "type": "bytes32" - } - ], - "name": "getTransactionAllData", - "outputs": [ - { - "components": [ - { - "internalType": "enum ITransactions.ResultType", - "name": "result", - "type": "uint8" - }, - { - "internalType": "enum ITransactions.VoteType", - "name": "txExecutionResult", - "type": "uint8" - }, - { - "internalType": "enum ITransactions.TransactionStatus", - "name": "previousStatus", - "type": "uint8" - }, - { - "internalType": "enum ITransactions.TransactionStatus", - "name": "status", - "type": "uint8" - }, - { - "internalType": "address", - "name": "txOrigin", - "type": "address" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "address", - "name": "activator", - "type": "address" - }, - { - "internalType": "uint256", - "name": "txSlot", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "initialRotations", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "numOfInitialValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "epoch", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "randomSeed", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "txExecutionHash", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "resultHash", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "txCalldata", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "eqBlocksOutputs", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "activationBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "processingBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "proposalBlock", - "type": "uint256" - } - ], - "internalType": "struct ITransactions.ReadStateBlockRange[]", - "name": "readStateBlockRanges", - "type": "tuple[]" - }, - { - "internalType": "uint256", - "name": "validUntil", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "internalType": "struct ITransactions.Transaction", - "name": "transaction", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "round", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "leaderIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "votesCommitted", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "votesRevealed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "appealBond", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "rotationsLeft", - "type": "uint256" - }, - { - "internalType": "enum ITransactions.ResultType", - "name": "result", - "type": "uint8" - }, - { - "internalType": "address[]", - "name": "roundValidators", - "type": "address[]" - }, - { - "internalType": "enum ITransactions.VoteType[]", - "name": "validatorVotes", - "type": "uint8[]" - }, - { - "internalType": "bytes32[]", - "name": "validatorVotesHash", - "type": "bytes32[]" - }, - { - "internalType": "bytes32[]", - "name": "validatorResultHash", - "type": "bytes32[]" - } - ], - "internalType": "struct ITransactions.RoundData[]", - "name": "roundsData", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_timestamp", - "type": "uint256" - } - ], - "name": "getTransactionData", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "currentTimestamp", - "type": "uint256" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "initialRotations", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "txSlot", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "createdTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lastVoteTimestamp", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "randomSeed", - "type": "bytes32" - }, - { - "internalType": "enum ITransactions.ResultType", - "name": "result", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "txExecutionHash", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "txCalldata", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "eqBlocksOutputs", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "enum IMessages.MessageType", - "name": "messageType", - "type": "uint8" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "bool", - "name": "onAcceptance", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "saltNonce", - "type": "uint256" - } - ], - "internalType": "struct IMessages.SubmittedMessage[]", - "name": "messages", - "type": "tuple[]" - }, - { - "internalType": "enum IQueues.QueueType", - "name": "queueType", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "queuePosition", - "type": "uint256" - }, - { - "internalType": "address", - "name": "activator", - "type": "address" - }, - { - "internalType": "address", - "name": "lastLeader", - "type": "address" - }, - { - "internalType": "enum ITransactions.TransactionStatus", - "name": "status", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "activationBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "processingBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "proposalBlock", - "type": "uint256" - } - ], - "internalType": "struct ITransactions.ReadStateBlockRange", - "name": "readStateBlockRange", - "type": "tuple" - }, - { - "internalType": "uint256", - "name": "numOfRounds", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "round", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "leaderIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "votesCommitted", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "votesRevealed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "appealBond", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "rotationsLeft", - "type": "uint256" - }, - { - "internalType": "enum ITransactions.ResultType", - "name": "result", - "type": "uint8" - }, - { - "internalType": "address[]", - "name": "roundValidators", - "type": "address[]" - }, - { - "internalType": "enum ITransactions.VoteType[]", - "name": "validatorVotes", - "type": "uint8[]" - }, - { - "internalType": "bytes32[]", - "name": "validatorVotesHash", - "type": "bytes32[]" - }, - { - "internalType": "bytes32[]", - "name": "validatorResultHash", - "type": "bytes32[]" - } - ], - "internalType": "struct ITransactions.RoundData", - "name": "lastRound", - "type": "tuple" - }, - { - "internalType": "address[]", - "name": "consumedValidators", - "type": "address[]" - } - ], - "internalType": "struct ConsensusData.TransactionData", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_timestamp", - "type": "uint256" - } - ], - "name": "getTransactionStatus", - "outputs": [ - { - "internalType": "enum ITransactions.TransactionStatus", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - } - ], - "name": "getValidatorsForLastRound", - "outputs": [ - { - "internalType": "address[]", - "name": "validators", - "type": "address[]" - } - ], - "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": "address", - "name": "_addressManager", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pendingOwner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "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": "address", - "name": "_addressManager", - "type": "address" - } - ], - "name": "setAddressManager", - "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": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } + { + "inputs": [], + "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": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTransactionStatus", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "status", + "type": "uint8" + } + ], + "name": "PhaseDeadlineNotInitialized", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrancyGuardReentrantCall", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "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": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "addressManager", + "outputs": [ + { + "internalType": "contract IAddressManager", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_currentTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_expectedDecisionId", + "type": "uint256" + } + ], + "name": "canFinalize", + "outputs": [ + { + "internalType": "bool", + "name": "ready", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "evaluatedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "appealDeadline", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + } + ], + "name": "estimateAppealBond", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + } + ], + "name": "estimateLatestAppealCharge", + "outputs": [ + { + "internalType": "uint256", + "name": "decisionId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "bond", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "funding", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "appealDeadline", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + } + ], + "name": "getCurrentActivator", + "outputs": [ + { + "internalType": "address", + "name": "newActivator", + "type": "address" + }, + { + "internalType": "bool", + "name": "activatorIsIdle", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "slots", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "secondsUntilNextBoundary", + "type": "uint256" + }, + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "currentStatus", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + } + ], + "name": "getCurrentLeader", + "outputs": [ + { + "internalType": "address", + "name": "newLeader", + "type": "address" + }, + { + "internalType": "bool", + "name": "leaderIsIdle", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "slots", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "secondsUntilNextBoundary", + "type": "uint256" + }, + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "currentStatus", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + } + ], + "name": "getCurrentValidators", + "outputs": [ + { + "internalType": "address[]", + "name": "validators", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "leaderIndex", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "idleIndexes", + "type": "uint256[]" + }, + { + "internalType": "bool", + "name": "leaderIsIdle", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "slots", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "secondsUntilNextBoundary", + "type": "uint256" + }, + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "currentStatus", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "getLatestAcceptedTransaction", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "observedAt", + "type": "uint256" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialRotations", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "txSlot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "createdTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lastVoteTimestamp", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "randomSeed", + "type": "bytes32" + }, + { + "internalType": "enum ITransactions.ResultType", + "name": "result", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "txExecutionHash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "txCalldata", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "eqBlocksOutputs", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "enum IMessages.MessageType", + "name": "messageType", + "type": "uint8" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "onAcceptance", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "saltNonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "feeParams", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "declaredBudget", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "allocationSubtree", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "callKey", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "useBalance", + "type": "bool" + } + ], + "internalType": "struct IMessages.SubmittedMessage[]", + "name": "messages", + "type": "tuple[]" + }, + { + "internalType": "enum IQueues.QueueType", + "name": "queueType", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "queuePosition", + "type": "uint256" + }, + { + "internalType": "address", + "name": "activator", + "type": "address" + }, + { + "internalType": "address", + "name": "lastLeader", + "type": "address" + }, + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "status", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "activationBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "processingBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "proposalBlock", + "type": "uint256" + } + ], + "internalType": "struct ITransactions.ReadStateBlockRange", + "name": "readStateBlockRange", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "numOfRounds", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "round", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "leaderIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "votesCommitted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "votesRevealed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "appealBond", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rotationsLeft", + "type": "uint256" + }, + { + "internalType": "enum ITransactions.ResultType", + "name": "result", + "type": "uint8" + }, + { + "internalType": "address[]", + "name": "roundValidators", + "type": "address[]" + }, + { + "internalType": "enum ITransactions.VoteType[]", + "name": "validatorVotes", + "type": "uint8[]" + }, + { + "internalType": "bytes32[]", + "name": "validatorVotesHash", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "validatorResultHash", + "type": "bytes32[]" + } + ], + "internalType": "struct ITransactions.RoundData", + "name": "lastRound", + "type": "tuple" + }, + { + "internalType": "address[]", + "name": "consumedValidators", + "type": "address[]" + } + ], + "internalType": "struct ConsensusData.TransactionData", + "name": "inputData", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "pageSize", + "type": "uint256" + } + ], + "name": "getLatestAcceptedTransactions", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "observedAt", + "type": "uint256" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialRotations", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "txSlot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "createdTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lastVoteTimestamp", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "randomSeed", + "type": "bytes32" + }, + { + "internalType": "enum ITransactions.ResultType", + "name": "result", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "txExecutionHash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "txCalldata", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "eqBlocksOutputs", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "enum IMessages.MessageType", + "name": "messageType", + "type": "uint8" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "onAcceptance", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "saltNonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "feeParams", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "declaredBudget", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "allocationSubtree", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "callKey", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "useBalance", + "type": "bool" + } + ], + "internalType": "struct IMessages.SubmittedMessage[]", + "name": "messages", + "type": "tuple[]" + }, + { + "internalType": "enum IQueues.QueueType", + "name": "queueType", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "queuePosition", + "type": "uint256" + }, + { + "internalType": "address", + "name": "activator", + "type": "address" + }, + { + "internalType": "address", + "name": "lastLeader", + "type": "address" + }, + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "status", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "activationBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "processingBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "proposalBlock", + "type": "uint256" + } + ], + "internalType": "struct ITransactions.ReadStateBlockRange", + "name": "readStateBlockRange", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "numOfRounds", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "round", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "leaderIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "votesCommitted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "votesRevealed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "appealBond", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rotationsLeft", + "type": "uint256" + }, + { + "internalType": "enum ITransactions.ResultType", + "name": "result", + "type": "uint8" + }, + { + "internalType": "address[]", + "name": "roundValidators", + "type": "address[]" + }, + { + "internalType": "enum ITransactions.VoteType[]", + "name": "validatorVotes", + "type": "uint8[]" + }, + { + "internalType": "bytes32[]", + "name": "validatorVotesHash", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "validatorResultHash", + "type": "bytes32[]" + } + ], + "internalType": "struct ITransactions.RoundData", + "name": "lastRound", + "type": "tuple" + }, + { + "internalType": "address[]", + "name": "consumedValidators", + "type": "address[]" + } + ], + "internalType": "struct ConsensusData.TransactionData[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "getLatestAcceptedTxCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "getLatestFinalizedTransaction", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "observedAt", + "type": "uint256" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialRotations", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "txSlot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "createdTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lastVoteTimestamp", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "randomSeed", + "type": "bytes32" + }, + { + "internalType": "enum ITransactions.ResultType", + "name": "result", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "txExecutionHash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "txCalldata", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "eqBlocksOutputs", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "enum IMessages.MessageType", + "name": "messageType", + "type": "uint8" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "onAcceptance", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "saltNonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "feeParams", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "declaredBudget", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "allocationSubtree", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "callKey", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "useBalance", + "type": "bool" + } + ], + "internalType": "struct IMessages.SubmittedMessage[]", + "name": "messages", + "type": "tuple[]" + }, + { + "internalType": "enum IQueues.QueueType", + "name": "queueType", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "queuePosition", + "type": "uint256" + }, + { + "internalType": "address", + "name": "activator", + "type": "address" + }, + { + "internalType": "address", + "name": "lastLeader", + "type": "address" + }, + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "status", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "activationBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "processingBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "proposalBlock", + "type": "uint256" + } + ], + "internalType": "struct ITransactions.ReadStateBlockRange", + "name": "readStateBlockRange", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "numOfRounds", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "round", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "leaderIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "votesCommitted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "votesRevealed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "appealBond", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rotationsLeft", + "type": "uint256" + }, + { + "internalType": "enum ITransactions.ResultType", + "name": "result", + "type": "uint8" + }, + { + "internalType": "address[]", + "name": "roundValidators", + "type": "address[]" + }, + { + "internalType": "enum ITransactions.VoteType[]", + "name": "validatorVotes", + "type": "uint8[]" + }, + { + "internalType": "bytes32[]", + "name": "validatorVotesHash", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "validatorResultHash", + "type": "bytes32[]" + } + ], + "internalType": "struct ITransactions.RoundData", + "name": "lastRound", + "type": "tuple" + }, + { + "internalType": "address[]", + "name": "consumedValidators", + "type": "address[]" + } + ], + "internalType": "struct ConsensusData.TransactionData", + "name": "inputData", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "pageSize", + "type": "uint256" + } + ], + "name": "getLatestFinalizedTransactions", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "observedAt", + "type": "uint256" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialRotations", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "txSlot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "createdTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lastVoteTimestamp", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "randomSeed", + "type": "bytes32" + }, + { + "internalType": "enum ITransactions.ResultType", + "name": "result", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "txExecutionHash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "txCalldata", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "eqBlocksOutputs", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "enum IMessages.MessageType", + "name": "messageType", + "type": "uint8" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "onAcceptance", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "saltNonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "feeParams", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "declaredBudget", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "allocationSubtree", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "callKey", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "useBalance", + "type": "bool" + } + ], + "internalType": "struct IMessages.SubmittedMessage[]", + "name": "messages", + "type": "tuple[]" + }, + { + "internalType": "enum IQueues.QueueType", + "name": "queueType", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "queuePosition", + "type": "uint256" + }, + { + "internalType": "address", + "name": "activator", + "type": "address" + }, + { + "internalType": "address", + "name": "lastLeader", + "type": "address" + }, + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "status", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "activationBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "processingBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "proposalBlock", + "type": "uint256" + } + ], + "internalType": "struct ITransactions.ReadStateBlockRange", + "name": "readStateBlockRange", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "numOfRounds", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "round", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "leaderIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "votesCommitted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "votesRevealed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "appealBond", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rotationsLeft", + "type": "uint256" + }, + { + "internalType": "enum ITransactions.ResultType", + "name": "result", + "type": "uint8" + }, + { + "internalType": "address[]", + "name": "roundValidators", + "type": "address[]" + }, + { + "internalType": "enum ITransactions.VoteType[]", + "name": "validatorVotes", + "type": "uint8[]" + }, + { + "internalType": "bytes32[]", + "name": "validatorVotesHash", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "validatorResultHash", + "type": "bytes32[]" + } + ], + "internalType": "struct ITransactions.RoundData", + "name": "lastRound", + "type": "tuple" + }, + { + "internalType": "address[]", + "name": "consumedValidators", + "type": "address[]" + } + ], + "internalType": "struct ConsensusData.TransactionData[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "getLatestFinalizedTxCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "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": "_txId", + "type": "bytes32" + } + ], + "name": "getStoredTransactionData", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "observedAt", + "type": "uint256" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialRotations", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "txSlot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "createdTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lastVoteTimestamp", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "randomSeed", + "type": "bytes32" + }, + { + "internalType": "enum ITransactions.ResultType", + "name": "result", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "txExecutionHash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "txCalldata", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "eqBlocksOutputs", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "enum IMessages.MessageType", + "name": "messageType", + "type": "uint8" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "onAcceptance", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "saltNonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "feeParams", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "declaredBudget", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "allocationSubtree", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "callKey", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "useBalance", + "type": "bool" + } + ], + "internalType": "struct IMessages.SubmittedMessage[]", + "name": "messages", + "type": "tuple[]" + }, + { + "internalType": "enum IQueues.QueueType", + "name": "queueType", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "queuePosition", + "type": "uint256" + }, + { + "internalType": "address", + "name": "activator", + "type": "address" + }, + { + "internalType": "address", + "name": "lastLeader", + "type": "address" + }, + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "status", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "activationBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "processingBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "proposalBlock", + "type": "uint256" + } + ], + "internalType": "struct ITransactions.ReadStateBlockRange", + "name": "readStateBlockRange", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "numOfRounds", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "round", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "leaderIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "votesCommitted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "votesRevealed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "appealBond", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rotationsLeft", + "type": "uint256" + }, + { + "internalType": "enum ITransactions.ResultType", + "name": "result", + "type": "uint8" + }, + { + "internalType": "address[]", + "name": "roundValidators", + "type": "address[]" + }, + { + "internalType": "enum ITransactions.VoteType[]", + "name": "validatorVotes", + "type": "uint8[]" + }, + { + "internalType": "bytes32[]", + "name": "validatorVotesHash", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "validatorResultHash", + "type": "bytes32[]" + } + ], + "internalType": "struct ITransactions.RoundData", + "name": "lastRound", + "type": "tuple" + }, + { + "internalType": "address[]", + "name": "consumedValidators", + "type": "address[]" + } + ], + "internalType": "struct ConsensusData.TransactionData", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + } + ], + "name": "getStoredTransactionStatus", + "outputs": [ + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + } + ], + "name": "getTransactionAllData", + "outputs": [ + { + "components": [ + { + "internalType": "enum ITransactions.ResultType", + "name": "result", + "type": "uint8" + }, + { + "internalType": "enum ITransactions.VoteType", + "name": "txExecutionResult", + "type": "uint8" + }, + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "status", + "type": "uint8" + }, + { + "internalType": "address", + "name": "txOrigin", + "type": "address" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "address", + "name": "activator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "txSlot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialRotations", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "numOfInitialValidators", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "randomSeed", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "txExecutionHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "resultHash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "txCalldata", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "eqBlocksOutputs", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "activationBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "processingBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "proposalBlock", + "type": "uint256" + } + ], + "internalType": "struct ITransactions.ReadStateBlockRange[]", + "name": "readStateBlockRanges", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "validUntil", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lockedStorageUnitPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "storageFeeUsed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lockedReceiptGasPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "txSigner", + "type": "address" + }, + { + "internalType": "enum ITransactions.QueueContext", + "name": "queueContext", + "type": "uint8" + } + ], + "internalType": "struct ITransactions.Transaction", + "name": "transaction", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "round", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "leaderIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "votesCommitted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "votesRevealed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "appealBond", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rotationsLeft", + "type": "uint256" + }, + { + "internalType": "enum ITransactions.ResultType", + "name": "result", + "type": "uint8" + }, + { + "internalType": "address[]", + "name": "roundValidators", + "type": "address[]" + }, + { + "internalType": "enum ITransactions.VoteType[]", + "name": "validatorVotes", + "type": "uint8[]" + }, + { + "internalType": "bytes32[]", + "name": "validatorVotesHash", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "validatorResultHash", + "type": "bytes32[]" + } + ], + "internalType": "struct ITransactions.RoundData[]", + "name": "roundsData", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_timestamp", + "type": "uint256" + } + ], + "name": "getTransactionLifecycle", + "outputs": [ + { + "components": [ + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "storedStatus", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "storedStatus", + "type": "uint8" + }, + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "projectedStatus", + "type": "uint8" + }, + { + "internalType": "enum IIdlenessPhase.ResolutionAction", + "name": "action", + "type": "uint8" + }, + { + "internalType": "enum ITransactions.ResultType", + "name": "result", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "resultHash", + "type": "bytes32" + }, + { + "internalType": "enum ITransactionManager.ResolutionSource", + "name": "source", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "sourceRound", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sourceGeneration", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "sourceRoundContextHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "roundPlanHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "resultRound", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "resultGeneration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "basisDecisionId", + "type": "uint256" + }, + { + "internalType": "enum ITransactionManager.ResolutionContext", + "name": "context", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "attemptId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "boundaryAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "evaluatedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "snapshotBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "decisionWindow", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "appealDeadline", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "materializesDecision", + "type": "bool" + }, + { + "internalType": "bool", + "name": "actionOutcomeDeterministic", + "type": "bool" + }, + { + "internalType": "bool", + "name": "nonCurrentEvaluation", + "type": "bool" + } + ], + "internalType": "struct IIdlenessPhase.ResolutionPlan", + "name": "resolution", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "decisionId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "basisDecisionId", + "type": "uint256" + }, + { + "internalType": "enum ITransactionManager.ResolutionContext", + "name": "context", + "type": "uint8" + }, + { + "internalType": "enum ITransactionManager.ResolutionSource", + "name": "source", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "sourceAttemptId", + "type": "bytes32" + }, + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "sourceStatus", + "type": "uint8" + }, + { + "internalType": "enum ITransactions.TransactionStatus", + "name": "status", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "sourceRound", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sourceGeneration", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "sourceRoundContextHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "roundPlanHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "resultRound", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "resultGeneration", + "type": "uint256" + }, + { + "internalType": "enum ITransactions.ResultType", + "name": "result", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "resultHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "effectiveAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "materializedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "appealDeadline", + "type": "uint256" + } + ], + "internalType": "struct ITransactionManager.DecisionRecord", + "name": "latestDecision", + "type": "tuple" + }, + { + "internalType": "bool", + "name": "decisionActive", + "type": "bool" + } + ], + "internalType": "struct ConsensusData.TransactionLifecycle", + "name": "lifecycle", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + } + ], + "name": "getValidatorsForLastRound", + "outputs": [ + { + "internalType": "address[]", + "name": "validators", + "type": "address[]" + } + ], + "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": "address", + "name": "_addressManager", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "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": "address", + "name": "_addressManager", + "type": "address" + } + ], + "name": "setAddressManager", + "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": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } ] diff --git a/genlayer_py/consensus/abi/consensus_data_big_rounds_abi.json b/genlayer_py/consensus/abi/consensus_data_big_rounds_abi.json new file mode 100644 index 0000000..b213b25 --- /dev/null +++ b/genlayer_py/consensus/abi/consensus_data_big_rounds_abi.json @@ -0,0 +1,115 @@ +[ + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + } + ], + "name": "getStoredTransactionDataLight", + "outputs": [ + { + "components": [ + {"internalType": "uint256", "name": "observedAt", "type": "uint256"}, + {"internalType": "address", "name": "sender", "type": "address"}, + {"internalType": "address", "name": "recipient", "type": "address"}, + {"internalType": "uint256", "name": "initialRotations", "type": "uint256"}, + {"internalType": "uint256", "name": "txSlot", "type": "uint256"}, + {"internalType": "uint256", "name": "createdTimestamp", "type": "uint256"}, + {"internalType": "uint256", "name": "lastVoteTimestamp", "type": "uint256"}, + {"internalType": "bytes32", "name": "randomSeed", "type": "bytes32"}, + {"internalType": "enum ITransactions.ResultType", "name": "result", "type": "uint8"}, + {"internalType": "bytes32", "name": "txExecutionHash", "type": "bytes32"}, + {"internalType": "bytes", "name": "txCalldata", "type": "bytes"}, + {"internalType": "bytes", "name": "eqBlocksOutputs", "type": "bytes"}, + { + "components": [ + {"internalType": "enum IMessages.MessageType", "name": "messageType", "type": "uint8"}, + {"internalType": "address", "name": "recipient", "type": "address"}, + {"internalType": "uint256", "name": "value", "type": "uint256"}, + {"internalType": "bytes", "name": "data", "type": "bytes"}, + {"internalType": "bool", "name": "onAcceptance", "type": "bool"}, + {"internalType": "uint256", "name": "saltNonce", "type": "uint256"}, + {"internalType": "bytes", "name": "feeParams", "type": "bytes"}, + {"internalType": "uint256", "name": "declaredBudget", "type": "uint256"}, + {"internalType": "bytes", "name": "allocationSubtree", "type": "bytes"}, + {"internalType": "bytes32", "name": "callKey", "type": "bytes32"}, + {"internalType": "bool", "name": "useBalance", "type": "bool"} + ], + "internalType": "struct IMessages.SubmittedMessage[]", + "name": "messages", + "type": "tuple[]" + }, + {"internalType": "enum IQueues.QueueType", "name": "queueType", "type": "uint8"}, + {"internalType": "uint256", "name": "queuePosition", "type": "uint256"}, + {"internalType": "address", "name": "activator", "type": "address"}, + {"internalType": "address", "name": "lastLeader", "type": "address"}, + {"internalType": "enum ITransactions.TransactionStatus", "name": "status", "type": "uint8"}, + {"internalType": "bytes32", "name": "txId", "type": "bytes32"}, + { + "components": [ + {"internalType": "uint256", "name": "activationBlock", "type": "uint256"}, + {"internalType": "uint256", "name": "processingBlock", "type": "uint256"}, + {"internalType": "uint256", "name": "proposalBlock", "type": "uint256"} + ], + "internalType": "struct ITransactions.ReadStateBlockRange", + "name": "readStateBlockRange", + "type": "tuple" + }, + {"internalType": "uint256", "name": "numOfRounds", "type": "uint256"}, + { + "components": [ + {"internalType": "uint256", "name": "round", "type": "uint256"}, + {"internalType": "uint256", "name": "leaderIndex", "type": "uint256"}, + {"internalType": "uint256", "name": "votesCommitted", "type": "uint256"}, + {"internalType": "uint256", "name": "votesRevealed", "type": "uint256"}, + {"internalType": "uint256", "name": "appealBond", "type": "uint256"}, + {"internalType": "uint256", "name": "rotationsLeft", "type": "uint256"}, + {"internalType": "enum ITransactions.ResultType", "name": "result", "type": "uint8"}, + {"internalType": "uint256", "name": "validatorsCount", "type": "uint256"} + ], + "internalType": "struct ConsensusDataBigRounds.RoundDataLight", + "name": "lastRound", + "type": "tuple" + }, + {"internalType": "uint256", "name": "consumedValidatorsCount", "type": "uint256"} + ], + "internalType": "struct ConsensusDataBigRounds.TransactionDataLight", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + {"internalType": "bytes32", "name": "_txId", "type": "bytes32"}, + {"internalType": "uint256", "name": "_round", "type": "uint256"}, + {"internalType": "uint256", "name": "_offset", "type": "uint256"}, + {"internalType": "uint256", "name": "_limit", "type": "uint256"} + ], + "name": "getRoundValidatorsPaged", + "outputs": [ + {"internalType": "address[]", "name": "page", "type": "address[]"}, + {"internalType": "uint256", "name": "total", "type": "uint256"} + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + {"internalType": "bytes32", "name": "_txId", "type": "bytes32"}, + {"internalType": "uint256", "name": "_offset", "type": "uint256"}, + {"internalType": "uint256", "name": "_limit", "type": "uint256"} + ], + "name": "getConsumedValidatorsPaged", + "outputs": [ + {"internalType": "address[]", "name": "page", "type": "address[]"}, + {"internalType": "uint256", "name": "total", "type": "uint256"} + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/genlayer_py/consensus/abi/consensus_data_lifecycle_abi.json b/genlayer_py/consensus/abi/consensus_data_lifecycle_abi.json new file mode 100644 index 0000000..8a44d30 --- /dev/null +++ b/genlayer_py/consensus/abi/consensus_data_lifecycle_abi.json @@ -0,0 +1,103 @@ +[ + { + "inputs": [], + "name": "addressManager", + "outputs": [ + {"internalType": "contract IAddressManager", "name": "", "type": "address"} + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + {"internalType": "bytes32", "name": "_txId", "type": "bytes32"}, + {"internalType": "uint256", "name": "_timestamp", "type": "uint256"} + ], + "name": "getTransactionLifecycle", + "outputs": [ + { + "components": [ + {"internalType": "enum ITransactions.TransactionStatus", "name": "storedStatus", "type": "uint8"}, + { + "components": [ + {"internalType": "bytes32", "name": "txId", "type": "bytes32"}, + {"internalType": "enum ITransactions.TransactionStatus", "name": "storedStatus", "type": "uint8"}, + {"internalType": "enum ITransactions.TransactionStatus", "name": "projectedStatus", "type": "uint8"}, + {"internalType": "enum IIdlenessPhase.ResolutionAction", "name": "action", "type": "uint8"}, + {"internalType": "enum ITransactions.ResultType", "name": "result", "type": "uint8"}, + {"internalType": "bytes32", "name": "resultHash", "type": "bytes32"}, + {"internalType": "enum ITransactionManager.ResolutionSource", "name": "source", "type": "uint8"}, + {"internalType": "uint256", "name": "sourceRound", "type": "uint256"}, + {"internalType": "uint256", "name": "sourceGeneration", "type": "uint256"}, + {"internalType": "bytes32", "name": "sourceRoundContextHash", "type": "bytes32"}, + {"internalType": "bytes32", "name": "roundPlanHash", "type": "bytes32"}, + {"internalType": "uint256", "name": "resultRound", "type": "uint256"}, + {"internalType": "uint256", "name": "resultGeneration", "type": "uint256"}, + {"internalType": "uint256", "name": "basisDecisionId", "type": "uint256"}, + {"internalType": "enum ITransactionManager.ResolutionContext", "name": "context", "type": "uint8"}, + {"internalType": "bytes32", "name": "attemptId", "type": "bytes32"}, + {"internalType": "uint256", "name": "boundaryAt", "type": "uint256"}, + {"internalType": "uint256", "name": "evaluatedAt", "type": "uint256"}, + {"internalType": "uint256", "name": "snapshotBlock", "type": "uint256"}, + {"internalType": "uint256", "name": "decisionWindow", "type": "uint256"}, + {"internalType": "uint256", "name": "appealDeadline", "type": "uint256"}, + {"internalType": "bool", "name": "materializesDecision", "type": "bool"}, + {"internalType": "bool", "name": "actionOutcomeDeterministic", "type": "bool"}, + {"internalType": "bool", "name": "nonCurrentEvaluation", "type": "bool"} + ], + "internalType": "struct IIdlenessPhase.ResolutionPlan", + "name": "resolution", + "type": "tuple" + }, + { + "components": [ + {"internalType": "bool", "name": "exists", "type": "bool"}, + {"internalType": "uint256", "name": "decisionId", "type": "uint256"}, + {"internalType": "uint256", "name": "basisDecisionId", "type": "uint256"}, + {"internalType": "enum ITransactionManager.ResolutionContext", "name": "context", "type": "uint8"}, + {"internalType": "enum ITransactionManager.ResolutionSource", "name": "source", "type": "uint8"}, + {"internalType": "bytes32", "name": "sourceAttemptId", "type": "bytes32"}, + {"internalType": "enum ITransactions.TransactionStatus", "name": "sourceStatus", "type": "uint8"}, + {"internalType": "enum ITransactions.TransactionStatus", "name": "status", "type": "uint8"}, + {"internalType": "uint256", "name": "sourceRound", "type": "uint256"}, + {"internalType": "uint256", "name": "sourceGeneration", "type": "uint256"}, + {"internalType": "bytes32", "name": "sourceRoundContextHash", "type": "bytes32"}, + {"internalType": "bytes32", "name": "roundPlanHash", "type": "bytes32"}, + {"internalType": "uint256", "name": "resultRound", "type": "uint256"}, + {"internalType": "uint256", "name": "resultGeneration", "type": "uint256"}, + {"internalType": "enum ITransactions.ResultType", "name": "result", "type": "uint8"}, + {"internalType": "bytes32", "name": "resultHash", "type": "bytes32"}, + {"internalType": "uint256", "name": "effectiveAt", "type": "uint256"}, + {"internalType": "uint256", "name": "materializedAt", "type": "uint256"}, + {"internalType": "uint256", "name": "appealDeadline", "type": "uint256"} + ], + "internalType": "struct ITransactionManager.DecisionRecord", + "name": "latestDecision", + "type": "tuple" + }, + {"internalType": "bool", "name": "decisionActive", "type": "bool"} + ], + "internalType": "struct ConsensusData.TransactionLifecycle", + "name": "lifecycle", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + {"internalType": "bytes32", "name": "_txId", "type": "bytes32"}, + {"internalType": "uint256", "name": "_currentTimestamp", "type": "uint256"}, + {"internalType": "uint256", "name": "_expectedDecisionId", "type": "uint256"} + ], + "name": "canFinalize", + "outputs": [ + {"internalType": "bool", "name": "ready", "type": "bool"}, + {"internalType": "uint256", "name": "evaluatedAt", "type": "uint256"}, + {"internalType": "uint256", "name": "appealDeadline", "type": "uint256"} + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/genlayer_py/consensus/abi/consensus_data_train_reads_abi.json b/genlayer_py/consensus/abi/consensus_data_train_reads_abi.json new file mode 100644 index 0000000..104da96 --- /dev/null +++ b/genlayer_py/consensus/abi/consensus_data_train_reads_abi.json @@ -0,0 +1,4 @@ +[ + {"inputs":[{"internalType":"bytes32","name":"_txId","type":"bytes32"}],"name":"getStoredTransactionData","outputs":[{"components":[{"internalType":"uint256","name":"observedAt","type":"uint256"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"initialRotations","type":"uint256"},{"internalType":"uint256","name":"txSlot","type":"uint256"},{"internalType":"uint256","name":"createdTimestamp","type":"uint256"},{"internalType":"uint256","name":"lastVoteTimestamp","type":"uint256"},{"internalType":"bytes32","name":"randomSeed","type":"bytes32"},{"internalType":"enum ITransactions.ResultType","name":"result","type":"uint8"},{"internalType":"bytes32","name":"txExecutionHash","type":"bytes32"},{"internalType":"bytes","name":"txCalldata","type":"bytes"},{"internalType":"bytes","name":"eqBlocksOutputs","type":"bytes"},{"components":[{"internalType":"enum IMessages.MessageType","name":"messageType","type":"uint8"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bool","name":"onAcceptance","type":"bool"},{"internalType":"uint256","name":"saltNonce","type":"uint256"},{"internalType":"bytes","name":"feeParams","type":"bytes"},{"internalType":"uint256","name":"declaredBudget","type":"uint256"},{"internalType":"bytes","name":"allocationSubtree","type":"bytes"},{"internalType":"bytes32","name":"callKey","type":"bytes32"},{"internalType":"bool","name":"useBalance","type":"bool"}],"internalType":"struct IMessages.SubmittedMessage[]","name":"messages","type":"tuple[]"},{"internalType":"enum IQueues.QueueType","name":"queueType","type":"uint8"},{"internalType":"uint256","name":"queuePosition","type":"uint256"},{"internalType":"address","name":"activator","type":"address"},{"internalType":"address","name":"lastLeader","type":"address"},{"internalType":"enum ITransactions.TransactionStatus","name":"status","type":"uint8"},{"internalType":"bytes32","name":"txId","type":"bytes32"},{"components":[{"internalType":"uint256","name":"activationBlock","type":"uint256"},{"internalType":"uint256","name":"processingBlock","type":"uint256"},{"internalType":"uint256","name":"proposalBlock","type":"uint256"}],"internalType":"struct ITransactions.ReadStateBlockRange","name":"readStateBlockRange","type":"tuple"},{"internalType":"uint256","name":"numOfRounds","type":"uint256"},{"components":[{"internalType":"uint256","name":"round","type":"uint256"},{"internalType":"uint256","name":"leaderIndex","type":"uint256"},{"internalType":"uint256","name":"votesCommitted","type":"uint256"},{"internalType":"uint256","name":"votesRevealed","type":"uint256"},{"internalType":"uint256","name":"appealBond","type":"uint256"},{"internalType":"uint256","name":"rotationsLeft","type":"uint256"},{"internalType":"enum ITransactions.ResultType","name":"result","type":"uint8"},{"internalType":"address[]","name":"roundValidators","type":"address[]"},{"internalType":"enum ITransactions.VoteType[]","name":"validatorVotes","type":"uint8[]"},{"internalType":"bytes32[]","name":"validatorVotesHash","type":"bytes32[]"},{"internalType":"bytes32[]","name":"validatorResultHash","type":"bytes32[]"}],"internalType":"struct ITransactions.RoundData","name":"lastRound","type":"tuple"},{"internalType":"address[]","name":"consumedValidators","type":"address[]"}],"internalType":"struct ConsensusData.TransactionData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"}, + {"inputs":[{"internalType":"bytes32","name":"_txId","type":"bytes32"}],"name":"getTransactionAllData","outputs":[{"components":[{"internalType":"enum ITransactions.ResultType","name":"result","type":"uint8"},{"internalType":"enum ITransactions.VoteType","name":"txExecutionResult","type":"uint8"},{"internalType":"enum ITransactions.TransactionStatus","name":"status","type":"uint8"},{"internalType":"address","name":"txOrigin","type":"address"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"activator","type":"address"},{"internalType":"uint256","name":"txSlot","type":"uint256"},{"internalType":"uint256","name":"initialRotations","type":"uint256"},{"internalType":"uint256","name":"numOfInitialValidators","type":"uint256"},{"internalType":"uint256","name":"epoch","type":"uint256"},{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"bytes32","name":"randomSeed","type":"bytes32"},{"internalType":"bytes32","name":"txExecutionHash","type":"bytes32"},{"internalType":"bytes32","name":"resultHash","type":"bytes32"},{"internalType":"bytes","name":"txCalldata","type":"bytes"},{"internalType":"bytes","name":"eqBlocksOutputs","type":"bytes"},{"components":[{"internalType":"uint256","name":"activationBlock","type":"uint256"},{"internalType":"uint256","name":"processingBlock","type":"uint256"},{"internalType":"uint256","name":"proposalBlock","type":"uint256"}],"internalType":"struct ITransactions.ReadStateBlockRange[]","name":"readStateBlockRanges","type":"tuple[]"},{"internalType":"uint256","name":"validUntil","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"lockedStorageUnitPrice","type":"uint256"},{"internalType":"uint256","name":"storageFeeUsed","type":"uint256"},{"internalType":"uint256","name":"lockedReceiptGasPrice","type":"uint256"},{"internalType":"address","name":"txSigner","type":"address"},{"internalType":"enum ITransactions.QueueContext","name":"queueContext","type":"uint8"}],"internalType":"struct ITransactions.Transaction","name":"transaction","type":"tuple"},{"components":[{"internalType":"uint256","name":"round","type":"uint256"},{"internalType":"uint256","name":"leaderIndex","type":"uint256"},{"internalType":"uint256","name":"votesCommitted","type":"uint256"},{"internalType":"uint256","name":"votesRevealed","type":"uint256"},{"internalType":"uint256","name":"appealBond","type":"uint256"},{"internalType":"uint256","name":"rotationsLeft","type":"uint256"},{"internalType":"enum ITransactions.ResultType","name":"result","type":"uint8"},{"internalType":"address[]","name":"roundValidators","type":"address[]"},{"internalType":"enum ITransactions.VoteType[]","name":"validatorVotes","type":"uint8[]"},{"internalType":"bytes32[]","name":"validatorVotesHash","type":"bytes32[]"},{"internalType":"bytes32[]","name":"validatorResultHash","type":"bytes32[]"}],"internalType":"struct ITransactions.RoundData[]","name":"roundsData","type":"tuple[]"}],"stateMutability":"view","type":"function"} +] diff --git a/genlayer_py/consensus/abi/consensus_main_abi.json b/genlayer_py/consensus/abi/consensus_main_abi.json index d6f97c3..c63e61e 100644 --- a/genlayer_py/consensus/abi/consensus_main_abi.json +++ b/genlayer_py/consensus/abi/consensus_main_abi.json @@ -1,1114 +1,2361 @@ [ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "oldActivator", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newActivator", - "type": "address" - } - ], - "name": "ActivatorReplaced", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "addressManager", - "type": "address" - } - ], - "name": "AddressManagerSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "enum ITransactions.TransactionStatus", - "name": "newStatus", - "type": "uint8" - } - ], - "name": "AllVotesCommitted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "appellant", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "bond", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "validators", - "type": "address[]" - } - ], - "name": "AppealStarted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "attempted", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "succeeded", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "failed", - "type": "uint256" - } - ], - "name": "BatchFinalizationCompleted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "txSlot", - "type": "uint256" - } - ], - "name": "CreatedTransaction", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "activator", - "type": "address" - } - ], - "name": "InternalMessageProcessed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "oldLeader", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newLeader", - "type": "address" - } - ], - "name": "LeaderIdlenessProcessed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "activator", - "type": "address" - } - ], - "name": "NewTransaction", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - } - ], - "name": "ProcessIdlenessAccepted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - } - ], - "name": "TransactionAccepted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "leader", - "type": "address" - } - ], - "name": "TransactionActivated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "cancelledBy", - "type": "address" - } - ], - "name": "TransactionCancelled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - } - ], - "name": "TransactionFinalizationFailed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - } - ], - "name": "TransactionFinalized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - } - ], - "name": "TransactionLeaderRevealed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "newLeader", - "type": "address" - } - ], - "name": "TransactionLeaderRotated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - } - ], - "name": "TransactionLeaderTimeout", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32[]", - "name": "txIds", - "type": "bytes32[]" - } - ], - "name": "TransactionNeedsRecomputation", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "validators", - "type": "address[]" - } - ], - "name": "TransactionReceiptProposed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - } - ], - "name": "TransactionUndetermined", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "tribunalIndex", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "TribunalAppealVoteCommitted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "tribunalIndex", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "indexed": false, - "internalType": "enum ITransactions.VoteType", - "name": "voteType", - "type": "uint8" - } - ], - "name": "TribunalAppealVoteRevealed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "oldValidator", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newValidator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "validatorIndex", - "type": "uint256" - } - ], - "name": "ValidatorReplaced", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "ValueWithdrawalFailed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "indexed": false, - "internalType": "bool", - "name": "isLastVote", - "type": "bool" - } - ], - "name": "VoteCommitted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "indexed": false, - "internalType": "enum ITransactions.VoteType", - "name": "voteType", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bool", - "name": "isLastVote", - "type": "bool" - }, - { - "indexed": false, - "internalType": "enum ITransactions.ResultType", - "name": "result", - "type": "uint8" - } - ], - "name": "VoteRevealed", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "_operator", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_vrfProof", - "type": "bytes" - } - ], - "name": "activateTransaction", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_sender", - "type": "address" - }, - { - "internalType": "address", - "name": "_recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_numOfInitialValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_maxRotations", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_calldata", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "_validUntil", - "type": "uint256" - } - ], - "name": "addTransaction", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - } - ], - "name": "cancelTransaction", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_tribunalIndex", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "_commitHash", - "type": "bytes32" - } - ], - "name": "commitTribunalAppealVote", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "_commitHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_validatorIndex", - "type": "uint256" - } - ], - "name": "commitVote", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_numOfInitialValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_maxRotations", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_calldata", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "_saltNonce", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_validUntil", - "type": "uint256" - } - ], - "name": "deploySalted", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "executeMessage", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[]", - "name": "_txIds", - "type": "bytes32[]" - } - ], - "name": "finalizeIdlenessTxs", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - } - ], - "name": "finalizeTransaction", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - } - ], - "name": "flushExternalMessages", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getAddressManager", - "outputs": [ - { - "internalType": "contract IAddressManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - } - ], - "name": "getPendingTransactionValue", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - } - ], - "name": "isGhostContract", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - } - ], - "name": "leaderIdleness", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "saltAsAValidator", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "txExecutionHash", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "messagesAndOtherFieldsHash", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "otherExecutionFieldsHash", - "type": "bytes32" - }, - { - "internalType": "enum ITransactions.VoteType", - "name": "resultValue", - "type": "uint8" - }, - { - "components": [ - { - "internalType": "enum IMessages.MessageType", - "name": "messageType", - "type": "uint8" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "bool", - "name": "onAcceptance", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "saltNonce", - "type": "uint256" - } - ], - "internalType": "struct IMessages.SubmittedMessage[]", - "name": "messages", - "type": "tuple[]" - } - ], - "internalType": "struct IConsensusMain.LeaderRevealVoteParams", - "name": "leaderRevealVoteParams", - "type": "tuple" - } - ], - "name": "leaderRevealVote", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - } - ], - "name": "processIdleness", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "_txExecutionHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_processingBlock", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_operator", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_eqBlocksOutputs", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "_vrfProof", - "type": "bytes" - } - ], - "name": "proposeReceipt", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[]", - "name": "_txIds", - "type": "bytes32[]" - } - ], - "name": "redButtonFinalize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "ghost", - "type": "address" - } - ], - "name": "registerGhostContract", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_tribunalIndex", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "_voteHash", - "type": "bytes32" - }, - { - "internalType": "enum ITransactions.VoteType", - "name": "_voteType", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "_otherExecutionFieldsHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_nonce", - "type": "uint256" - } - ], - "name": "revealTribunalAppealVote", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "_voteHash", - "type": "bytes32" - }, - { - "internalType": "enum ITransactions.VoteType", - "name": "_voteType", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "_otherExecutionFieldsHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_nonce", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_validatorIndex", - "type": "uint256" - } - ], - "name": "revealVote", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_addressManager", - "type": "address" - } - ], - "name": "setAddressManager", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - } - ], - "name": "submitAppeal", - "outputs": [], - "stateMutability": "payable", - "type": "function" - } + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "CallerNotMessages", + "type": "error" + }, + { + "inputs": [], + "name": "CanNotAppeal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "attemptedConsumption", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "budget", + "type": "uint256" + } + ], + "name": "ExecutionBudgetExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientFees", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDeploymentWithSalt", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRevealLeaderData", + "type": "error" + }, + { + "inputs": [], + "name": "LegacyProposeReceiptRetired", + "type": "error" + }, + { + "inputs": [], + "name": "MessageFeesTotalMustBeNonZero", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrancyGuardReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "RollupBudgetBelowFloor", + "type": "error" + }, + { + "inputs": [], + "name": "Unauthorized", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "oldActivator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newActivator", + "type": "address" + } + ], + "name": "ActivatorReplaced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "addressManager", + "type": "address" + } + ], + "name": "AddressManagerSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "enum ITransactions.TransactionStatus", + "name": "newStatus", + "type": "uint8" + } + ], + "name": "AllVotesCommitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "appealer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "AppealBondReturned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "appellant", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "bond", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "validators", + "type": "address[]" + } + ], + "name": "AppealStarted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "appealer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "bondReturned", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "profitUnpaid", + "type": "uint256" + } + ], + "name": "AppealerProfitPayoutFailed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint8", + "name": "commandKind", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes4", + "name": "errorSelector", + "type": "bytes4" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "failureFingerprint", + "type": "bytes32" + } + ], + "name": "BatchCommandFailed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "attempted", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "finalized", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "progressed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "failed", + "type": "uint256" + } + ], + "name": "BatchFinalizationCompleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "attempted", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "resolved", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "failed", + "type": "uint256" + } + ], + "name": "BatchResolutionCompleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "txSlot", + "type": "uint256" + } + ], + "name": "CreatedTransaction", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FeesRefunded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "activator", + "type": "address" + } + ], + "name": "InternalMessageProcessed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "oldLeader", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newLeader", + "type": "address" + } + ], + "name": "LeaderIdlenessProcessed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "activator", + "type": "address" + } + ], + "name": "NewTransaction", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "firstAnnouncedAt", + "type": "uint256" + } + ], + "name": "NewTransactionAlreadyAnnounced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + } + ], + "name": "ProcessIdlenessAccepted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "receiptFee", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasPrice", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "estimatedGas", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "receiptBytes", + "type": "uint256" + } + ], + "name": "ReceiptFeeEstimated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + } + ], + "name": "TransactionAccepted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "leader", + "type": "address" + } + ], + "name": "TransactionActivated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "cancelledBy", + "type": "address" + } + ], + "name": "TransactionCancelled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + } + ], + "name": "TransactionFinalized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + } + ], + "name": "TransactionLeaderRevealed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "newLeader", + "type": "address" + } + ], + "name": "TransactionLeaderRotated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + } + ], + "name": "TransactionLeaderTimeout", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32[]", + "name": "txIds", + "type": "bytes32[]" + } + ], + "name": "TransactionNeedsRecomputation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "validators", + "type": "address[]" + } + ], + "name": "TransactionReceiptProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + } + ], + "name": "TransactionUndetermined", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tribunalIndex", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "TribunalAppealVoteCommitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tribunalIndex", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum ITransactions.VoteType", + "name": "voteType", + "type": "uint8" + } + ], + "name": "TribunalAppealVoteRevealed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "chunkIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "recipients", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "name": "UnifiedFeesDistributed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "UserValueRefunded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "oldValidator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newValidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "validatorIndex", + "type": "uint256" + } + ], + "name": "ValidatorReplaced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "ValueWithdrawalFailed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "isLastVote", + "type": "bool" + } + ], + "name": "VoteCommitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum ITransactions.VoteType", + "name": "voteType", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bool", + "name": "isLastVote", + "type": "bool" + }, + { + "indexed": false, + "internalType": "enum ITransactions.ResultType", + "name": "result", + "type": "uint8" + } + ], + "name": "VoteRevealed", + "type": "event" + }, + { + "inputs": [], + "name": "EVENTS_BATCH_SIZE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "_vrfProof", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "_expectedAttemptId", + "type": "bytes32" + } + ], + "name": "activateTransaction", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_expectedAttemptId", + "type": "bytes32" + } + ], + "name": "activatorIdleness", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "numOfInitialValidators", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxRotations", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validUntil", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "saltNonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "userValue", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "leaderTimeunitsAllocation", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validatorTimeunitsAllocation", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "appealRounds", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "executionBudgetPerRound", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "executionConsumed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalMessageFees", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "rotations", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "maxPriceGenPerTimeUnit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "storageFeeMaxGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "receiptFeeMaxGasPrice", + "type": "uint256" + } + ], + "internalType": "struct IFeeManager.FeesDistribution", + "name": "feesDistribution", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "txCalldata", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "enum IMessages.MessageType", + "name": "messageType", + "type": "uint8" + }, + { + "internalType": "bool", + "name": "onAcceptance", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "parentIndex", + "type": "uint256" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "callKey", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "budget", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "feeParams", + "type": "bytes" + } + ], + "internalType": "struct IMessages.MessageFeeAllocationNode[]", + "name": "messageAllocations", + "type": "tuple[]" + } + ], + "internalType": "struct IConsensusMainWithFees.AddTransactionParams", + "name": "_params", + "type": "tuple" + } + ], + "name": "addTransaction", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "addressManager", + "outputs": [ + { + "internalType": "contract IAddressManager", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + } + ], + "name": "cancelTransaction", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_commitHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_validatorIndex", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "_expectedAttemptId", + "type": "bytes32" + } + ], + "name": "commitVote", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "numOfInitialValidators", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxRotations", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validUntil", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "saltNonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "userValue", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "leaderTimeunitsAllocation", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validatorTimeunitsAllocation", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "appealRounds", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "executionBudgetPerRound", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "executionConsumed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalMessageFees", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "rotations", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "maxPriceGenPerTimeUnit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "storageFeeMaxGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "receiptFeeMaxGasPrice", + "type": "uint256" + } + ], + "internalType": "struct IFeeManager.FeesDistribution", + "name": "feesDistribution", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "txCalldata", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "enum IMessages.MessageType", + "name": "messageType", + "type": "uint8" + }, + { + "internalType": "bool", + "name": "onAcceptance", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "parentIndex", + "type": "uint256" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "callKey", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "budget", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "feeParams", + "type": "bytes" + } + ], + "internalType": "struct IMessages.MessageFeeAllocationNode[]", + "name": "messageAllocations", + "type": "tuple[]" + } + ], + "internalType": "struct IConsensusMainWithFees.AddTransactionParams", + "name": "_params", + "type": "tuple" + } + ], + "name": "deploySalted", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_expectedDecisionId", + "type": "uint256" + } + ], + "name": "estimateAppealCharge", + "outputs": [ + { + "internalType": "uint256", + "name": "bond", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "funding", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "_gasLimit", + "type": "uint256" + } + ], + "name": "executeMessage", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "expectedDecisionId", + "type": "uint256" + } + ], + "internalType": "struct IFinalizationPhase.FinalizeTransactionParams", + "name": "command", + "type": "tuple" + } + ], + "name": "finalizeDecisionBatchItem", + "outputs": [ + { + "internalType": "uint8", + "name": "outcome", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "expectedDecisionId", + "type": "uint256" + } + ], + "internalType": "struct IFinalizationPhase.FinalizeTransactionParams[]", + "name": "_commands", + "type": "tuple[]" + } + ], + "name": "finalizeDecisions", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_expectedDecisionId", + "type": "uint256" + } + ], + "name": "finalizeTransaction", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + } + ], + "name": "flushExternalMessages", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + } + ], + "name": "flushInternalMessages", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAddressManager", + "outputs": [ + { + "internalType": "contract IAddressManager", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + } + ], + "name": "getPendingTransactionValue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_addressManager", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "isAuthorizedGhostCaller", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "isGhostContract", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_expectedAttemptId", + "type": "bytes32" + } + ], + "name": "leaderIdleness", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "expectedAttemptId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "saltAsAValidator", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "txExecutionHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "messagesAndOtherFieldsHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "otherExecutionFieldsHash", + "type": "bytes32" + }, + { + "internalType": "enum ITransactions.VoteType", + "name": "resultValue", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "enum IMessages.MessageType", + "name": "messageType", + "type": "uint8" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "onAcceptance", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "saltNonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "feeParams", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "declaredBudget", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "allocationSubtree", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "callKey", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "useBalance", + "type": "bool" + } + ], + "internalType": "struct IMessages.SubmittedMessage[]", + "name": "messages", + "type": "tuple[]" + } + ], + "internalType": "struct IConsensusMainWithFees.LeaderRevealVoteParams", + "name": "leaderRevealVoteParams", + "type": "tuple" + } + ], + "name": "leaderRevealVote", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_expectedAttemptId", + "type": "bytes32" + } + ], + "name": "processIdleness", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "recipients", + "type": "address[]" + } + ], + "name": "promoteNextPendingTransactions", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "proposeReceipt", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_txExecutionHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_processingBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_storageFeeUsed", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_eqBlocksOutputs", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "_vrfProof", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "_expectedAttemptId", + "type": "bytes32" + } + ], + "name": "proposeReceipt", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_txExecutionHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_processingBlock", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_eqBlocksOutputs", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "_vrfProof", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "_expectedAttemptId", + "type": "bytes32" + } + ], + "name": "proposeReceipt", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_txExecutionHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_processingBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_storageFeeUsed", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_eqBlocksOutputs", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "_vrfProof", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "_reportedMessageFeesTotal", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "_expectedAttemptId", + "type": "bytes32" + } + ], + "name": "proposeReceiptWithMessages", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "ghost", + "type": "address" + } + ], + "name": "registerGhostContract", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "expectedAttemptId", + "type": "bytes32" + } + ], + "internalType": "struct IIdlenessPhase.ProcessIdlenessParams", + "name": "command", + "type": "tuple" + } + ], + "name": "resolveTransactionBatchItem", + "outputs": [ + { + "internalType": "uint8", + "name": "outcome", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "expectedAttemptId", + "type": "bytes32" + } + ], + "internalType": "struct IIdlenessPhase.ProcessIdlenessParams[]", + "name": "_commands", + "type": "tuple[]" + } + ], + "name": "resolveTransactions", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_voteHash", + "type": "bytes32" + }, + { + "internalType": "enum ITransactions.VoteType", + "name": "_voteType", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "_otherExecutionFieldsHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_validatorIndex", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "_expectedAttemptId", + "type": "bytes32" + } + ], + "name": "revealVote", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_addressManager", + "type": "address" + } + ], + "name": "setAddressManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_expectedDecisionId", + "type": "uint256" + } + ], + "name": "submitAppeal", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_expectedDecisionId", + "type": "uint256" + } + ], + "name": "topUpAndProgressFinalization", + "outputs": [ + { + "internalType": "bool", + "name": "finalized", + "type": "bool" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_expectedDecisionId", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "leaderTimeunitsAllocation", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validatorTimeunitsAllocation", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "appealRounds", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "executionBudgetPerRound", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "executionConsumed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalMessageFees", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "rotations", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "maxPriceGenPerTimeUnit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "storageFeeMaxGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "receiptFeeMaxGasPrice", + "type": "uint256" + } + ], + "internalType": "struct IFeeManager.FeesDistribution", + "name": "", + "type": "tuple" + } + ], + "name": "topUpAndSubmitAppeal", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "leaderTimeunitsAllocation", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validatorTimeunitsAllocation", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "appealRounds", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "executionBudgetPerRound", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "executionConsumed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalMessageFees", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "rotations", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "maxPriceGenPerTimeUnit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "storageFeeMaxGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "receiptFeeMaxGasPrice", + "type": "uint256" + } + ], + "internalType": "struct IFeeManager.FeesDistribution", + "name": "_feesDistribution", + "type": "tuple" + } + ], + "name": "topUpFees", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferEthOnBehalf", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } ] diff --git a/genlayer_py/consensus/abi/consensus_main_abi_v06.json b/genlayer_py/consensus/abi/consensus_main_abi_v06.json index 7b0b9dd..c63e61e 100644 --- a/genlayer_py/consensus/abi/consensus_main_abi_v06.json +++ b/genlayer_py/consensus/abi/consensus_main_abi_v06.json @@ -1,1346 +1,2361 @@ [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "CallerNotMessages", - "type": "error" - }, - { - "inputs": [], - "name": "CanNotAppeal", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDeploymentWithSalt", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidGhostContract", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidInitialization", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRevealLeaderData", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidVote", - "type": "error" - }, - { - "inputs": [], - "name": "NotInitializing", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "OwnableInvalidOwner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "OwnableUnauthorizedAccount", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrancyGuardReentrantCall", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "oldActivator", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newActivator", - "type": "address" - } - ], - "name": "ActivatorReplaced", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "addressManager", - "type": "address" - } - ], - "name": "AddressManagerSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "enum ITransactions.TransactionStatus", - "name": "newStatus", - "type": "uint8" - } - ], - "name": "AllVotesCommitted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "appellant", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "bond", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "validators", - "type": "address[]" - } - ], - "name": "AppealStarted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "attempted", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "succeeded", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "failed", - "type": "uint256" - } - ], - "name": "BatchFinalizationCompleted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "txSlot", - "type": "uint256" - } - ], - "name": "CreatedTransaction", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "version", - "type": "uint64" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "activator", - "type": "address" - } - ], - "name": "InternalMessageProcessed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "oldLeader", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newLeader", - "type": "address" - } - ], - "name": "LeaderIdlenessProcessed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "activator", - "type": "address" - } - ], - "name": "NewTransaction", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferStarted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - } - ], - "name": "ProcessIdlenessAccepted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - } - ], - "name": "TransactionAccepted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "leader", - "type": "address" - } - ], - "name": "TransactionActivated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "cancelledBy", - "type": "address" - } - ], - "name": "TransactionCancelled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - } - ], - "name": "TransactionFinalizationFailed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - } - ], - "name": "TransactionFinalized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - } - ], - "name": "TransactionLeaderRevealed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "newLeader", - "type": "address" - } - ], - "name": "TransactionLeaderRotated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - } - ], - "name": "TransactionLeaderTimeout", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32[]", - "name": "txIds", - "type": "bytes32[]" - } - ], - "name": "TransactionNeedsRecomputation", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "validators", - "type": "address[]" - } - ], - "name": "TransactionReceiptProposed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - } - ], - "name": "TransactionUndetermined", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "tribunalIndex", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "TribunalAppealVoteCommitted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "tribunalIndex", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "indexed": false, - "internalType": "enum ITransactions.VoteType", - "name": "voteType", - "type": "uint8" - } - ], - "name": "TribunalAppealVoteRevealed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "oldValidator", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newValidator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "validatorIndex", - "type": "uint256" - } - ], - "name": "ValidatorReplaced", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "ValueWithdrawalFailed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "indexed": false, - "internalType": "bool", - "name": "isLastVote", - "type": "bool" - } - ], - "name": "VoteCommitted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "indexed": false, - "internalType": "enum ITransactions.VoteType", - "name": "voteType", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bool", - "name": "isLastVote", - "type": "bool" - }, - { - "indexed": false, - "internalType": "enum ITransactions.ResultType", - "name": "result", - "type": "uint8" - } - ], - "name": "VoteRevealed", - "type": "event" - }, - { - "inputs": [], - "name": "EVENTS_BATCH_SIZE", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VERSION", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "_operator", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_vrfProof", - "type": "bytes" - } - ], - "name": "activateTransaction", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_sender", - "type": "address" - }, - { - "internalType": "address", - "name": "_recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_numOfInitialValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_maxRotations", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_calldata", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "_validUntil", - "type": "uint256" - } - ], - "name": "addTransaction", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "addressManager", - "outputs": [ - { - "internalType": "contract IAddressManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - } - ], - "name": "cancelTransaction", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_tribunalIndex", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "_commitHash", - "type": "bytes32" - } - ], - "name": "commitTribunalAppealVote", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "_commitHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_validatorIndex", - "type": "uint256" - } - ], - "name": "commitVote", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_numOfInitialValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_maxRotations", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_calldata", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "_saltNonce", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_validUntil", - "type": "uint256" - } - ], - "name": "deploySalted", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "executeMessage", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[]", - "name": "_txIds", - "type": "bytes32[]" - } - ], - "name": "finalizeIdlenessTxs", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - } - ], - "name": "finalizeTransaction", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - } - ], - "name": "flushExternalMessages", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getAddressManager", - "outputs": [ - { - "internalType": "contract IAddressManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - } - ], - "name": "getPendingTransactionValue", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_addressManager", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - } - ], - "name": "isGhostContract", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - } - ], - "name": "leaderIdleness", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "saltAsAValidator", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "txExecutionHash", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "messagesAndOtherFieldsHash", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "otherExecutionFieldsHash", - "type": "bytes32" - }, - { - "internalType": "enum ITransactions.VoteType", - "name": "resultValue", - "type": "uint8" - }, - { - "components": [ - { - "internalType": "enum IMessages.MessageType", - "name": "messageType", - "type": "uint8" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "bool", - "name": "onAcceptance", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "saltNonce", - "type": "uint256" - } - ], - "internalType": "struct IMessages.SubmittedMessage[]", - "name": "messages", - "type": "tuple[]" - } - ], - "internalType": "struct IConsensusMain.LeaderRevealVoteParams", - "name": "leaderRevealVoteParams", - "type": "tuple" - } - ], - "name": "leaderRevealVote", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pendingOwner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - } - ], - "name": "processIdleness", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "_txExecutionHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_processingBlock", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_operator", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_eqBlocksOutputs", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "_vrfProof", - "type": "bytes" - } - ], - "name": "proposeReceipt", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[]", - "name": "_txIds", - "type": "bytes32[]" - } - ], - "name": "redButtonFinalize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "ghost", - "type": "address" - } - ], - "name": "registerGhostContract", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_tribunalIndex", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "_voteHash", - "type": "bytes32" - }, - { - "internalType": "enum ITransactions.VoteType", - "name": "_voteType", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "_otherExecutionFieldsHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_nonce", - "type": "uint256" - } - ], - "name": "revealTribunalAppealVote", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "_voteHash", - "type": "bytes32" - }, - { - "internalType": "enum ITransactions.VoteType", - "name": "_voteType", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "_otherExecutionFieldsHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_nonce", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_validatorIndex", - "type": "uint256" - } - ], - "name": "revealVote", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_addressManager", - "type": "address" - } - ], - "name": "setAddressManager", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - } - ], - "name": "submitAppeal", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "CallerNotMessages", + "type": "error" + }, + { + "inputs": [], + "name": "CanNotAppeal", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "attemptedConsumption", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "budget", + "type": "uint256" + } + ], + "name": "ExecutionBudgetExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientFees", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDeploymentWithSalt", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRevealLeaderData", + "type": "error" + }, + { + "inputs": [], + "name": "LegacyProposeReceiptRetired", + "type": "error" + }, + { + "inputs": [], + "name": "MessageFeesTotalMustBeNonZero", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrancyGuardReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "RollupBudgetBelowFloor", + "type": "error" + }, + { + "inputs": [], + "name": "Unauthorized", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "oldActivator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newActivator", + "type": "address" + } + ], + "name": "ActivatorReplaced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "addressManager", + "type": "address" + } + ], + "name": "AddressManagerSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "enum ITransactions.TransactionStatus", + "name": "newStatus", + "type": "uint8" + } + ], + "name": "AllVotesCommitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "appealer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "AppealBondReturned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "appellant", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "bond", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "validators", + "type": "address[]" + } + ], + "name": "AppealStarted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "appealer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "bondReturned", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "profitUnpaid", + "type": "uint256" + } + ], + "name": "AppealerProfitPayoutFailed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint8", + "name": "commandKind", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes4", + "name": "errorSelector", + "type": "bytes4" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "failureFingerprint", + "type": "bytes32" + } + ], + "name": "BatchCommandFailed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "attempted", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "finalized", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "progressed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "failed", + "type": "uint256" + } + ], + "name": "BatchFinalizationCompleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "attempted", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "resolved", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "failed", + "type": "uint256" + } + ], + "name": "BatchResolutionCompleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "txSlot", + "type": "uint256" + } + ], + "name": "CreatedTransaction", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FeesRefunded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "activator", + "type": "address" + } + ], + "name": "InternalMessageProcessed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "oldLeader", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newLeader", + "type": "address" + } + ], + "name": "LeaderIdlenessProcessed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "activator", + "type": "address" + } + ], + "name": "NewTransaction", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "firstAnnouncedAt", + "type": "uint256" + } + ], + "name": "NewTransactionAlreadyAnnounced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + } + ], + "name": "ProcessIdlenessAccepted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "receiptFee", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasPrice", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "estimatedGas", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "receiptBytes", + "type": "uint256" + } + ], + "name": "ReceiptFeeEstimated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + } + ], + "name": "TransactionAccepted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "leader", + "type": "address" + } + ], + "name": "TransactionActivated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "cancelledBy", + "type": "address" + } + ], + "name": "TransactionCancelled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + } + ], + "name": "TransactionFinalized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + } + ], + "name": "TransactionLeaderRevealed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "newLeader", + "type": "address" + } + ], + "name": "TransactionLeaderRotated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + } + ], + "name": "TransactionLeaderTimeout", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32[]", + "name": "txIds", + "type": "bytes32[]" + } + ], + "name": "TransactionNeedsRecomputation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "validators", + "type": "address[]" + } + ], + "name": "TransactionReceiptProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + } + ], + "name": "TransactionUndetermined", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tribunalIndex", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "TribunalAppealVoteCommitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tribunalIndex", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum ITransactions.VoteType", + "name": "voteType", + "type": "uint8" + } + ], + "name": "TribunalAppealVoteRevealed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "chunkIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "recipients", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "name": "UnifiedFeesDistributed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "UserValueRefunded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "oldValidator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newValidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "validatorIndex", + "type": "uint256" + } + ], + "name": "ValidatorReplaced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "ValueWithdrawalFailed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "isLastVote", + "type": "bool" + } + ], + "name": "VoteCommitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum ITransactions.VoteType", + "name": "voteType", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bool", + "name": "isLastVote", + "type": "bool" + }, + { + "indexed": false, + "internalType": "enum ITransactions.ResultType", + "name": "result", + "type": "uint8" + } + ], + "name": "VoteRevealed", + "type": "event" + }, + { + "inputs": [], + "name": "EVENTS_BATCH_SIZE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "_vrfProof", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "_expectedAttemptId", + "type": "bytes32" + } + ], + "name": "activateTransaction", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_expectedAttemptId", + "type": "bytes32" + } + ], + "name": "activatorIdleness", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "numOfInitialValidators", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxRotations", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validUntil", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "saltNonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "userValue", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "leaderTimeunitsAllocation", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validatorTimeunitsAllocation", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "appealRounds", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "executionBudgetPerRound", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "executionConsumed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalMessageFees", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "rotations", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "maxPriceGenPerTimeUnit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "storageFeeMaxGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "receiptFeeMaxGasPrice", + "type": "uint256" + } + ], + "internalType": "struct IFeeManager.FeesDistribution", + "name": "feesDistribution", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "txCalldata", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "enum IMessages.MessageType", + "name": "messageType", + "type": "uint8" + }, + { + "internalType": "bool", + "name": "onAcceptance", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "parentIndex", + "type": "uint256" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "callKey", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "budget", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "feeParams", + "type": "bytes" + } + ], + "internalType": "struct IMessages.MessageFeeAllocationNode[]", + "name": "messageAllocations", + "type": "tuple[]" + } + ], + "internalType": "struct IConsensusMainWithFees.AddTransactionParams", + "name": "_params", + "type": "tuple" + } + ], + "name": "addTransaction", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "addressManager", + "outputs": [ + { + "internalType": "contract IAddressManager", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + } + ], + "name": "cancelTransaction", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_commitHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_validatorIndex", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "_expectedAttemptId", + "type": "bytes32" + } + ], + "name": "commitVote", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "numOfInitialValidators", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxRotations", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validUntil", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "saltNonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "userValue", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "leaderTimeunitsAllocation", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validatorTimeunitsAllocation", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "appealRounds", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "executionBudgetPerRound", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "executionConsumed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalMessageFees", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "rotations", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "maxPriceGenPerTimeUnit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "storageFeeMaxGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "receiptFeeMaxGasPrice", + "type": "uint256" + } + ], + "internalType": "struct IFeeManager.FeesDistribution", + "name": "feesDistribution", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "txCalldata", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "enum IMessages.MessageType", + "name": "messageType", + "type": "uint8" + }, + { + "internalType": "bool", + "name": "onAcceptance", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "parentIndex", + "type": "uint256" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "callKey", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "budget", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "feeParams", + "type": "bytes" + } + ], + "internalType": "struct IMessages.MessageFeeAllocationNode[]", + "name": "messageAllocations", + "type": "tuple[]" + } + ], + "internalType": "struct IConsensusMainWithFees.AddTransactionParams", + "name": "_params", + "type": "tuple" + } + ], + "name": "deploySalted", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_expectedDecisionId", + "type": "uint256" + } + ], + "name": "estimateAppealCharge", + "outputs": [ + { + "internalType": "uint256", + "name": "bond", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "funding", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "_gasLimit", + "type": "uint256" + } + ], + "name": "executeMessage", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "expectedDecisionId", + "type": "uint256" + } + ], + "internalType": "struct IFinalizationPhase.FinalizeTransactionParams", + "name": "command", + "type": "tuple" + } + ], + "name": "finalizeDecisionBatchItem", + "outputs": [ + { + "internalType": "uint8", + "name": "outcome", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "expectedDecisionId", + "type": "uint256" + } + ], + "internalType": "struct IFinalizationPhase.FinalizeTransactionParams[]", + "name": "_commands", + "type": "tuple[]" + } + ], + "name": "finalizeDecisions", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_expectedDecisionId", + "type": "uint256" + } + ], + "name": "finalizeTransaction", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + } + ], + "name": "flushExternalMessages", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + } + ], + "name": "flushInternalMessages", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAddressManager", + "outputs": [ + { + "internalType": "contract IAddressManager", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + } + ], + "name": "getPendingTransactionValue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_addressManager", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "isAuthorizedGhostCaller", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "isGhostContract", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_expectedAttemptId", + "type": "bytes32" + } + ], + "name": "leaderIdleness", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "expectedAttemptId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "saltAsAValidator", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "txExecutionHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "messagesAndOtherFieldsHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "otherExecutionFieldsHash", + "type": "bytes32" + }, + { + "internalType": "enum ITransactions.VoteType", + "name": "resultValue", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "enum IMessages.MessageType", + "name": "messageType", + "type": "uint8" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "onAcceptance", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "saltNonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "feeParams", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "declaredBudget", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "allocationSubtree", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "callKey", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "useBalance", + "type": "bool" + } + ], + "internalType": "struct IMessages.SubmittedMessage[]", + "name": "messages", + "type": "tuple[]" + } + ], + "internalType": "struct IConsensusMainWithFees.LeaderRevealVoteParams", + "name": "leaderRevealVoteParams", + "type": "tuple" + } + ], + "name": "leaderRevealVote", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_expectedAttemptId", + "type": "bytes32" + } + ], + "name": "processIdleness", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "recipients", + "type": "address[]" + } + ], + "name": "promoteNextPendingTransactions", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "proposeReceipt", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_txExecutionHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_processingBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_storageFeeUsed", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_eqBlocksOutputs", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "_vrfProof", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "_expectedAttemptId", + "type": "bytes32" + } + ], + "name": "proposeReceipt", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_txExecutionHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_processingBlock", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_eqBlocksOutputs", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "_vrfProof", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "_expectedAttemptId", + "type": "bytes32" + } + ], + "name": "proposeReceipt", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_txExecutionHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_processingBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_storageFeeUsed", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_eqBlocksOutputs", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "_vrfProof", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "_reportedMessageFeesTotal", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "_expectedAttemptId", + "type": "bytes32" + } + ], + "name": "proposeReceiptWithMessages", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "ghost", + "type": "address" + } + ], + "name": "registerGhostContract", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "expectedAttemptId", + "type": "bytes32" + } + ], + "internalType": "struct IIdlenessPhase.ProcessIdlenessParams", + "name": "command", + "type": "tuple" + } + ], + "name": "resolveTransactionBatchItem", + "outputs": [ + { + "internalType": "uint8", + "name": "outcome", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "expectedAttemptId", + "type": "bytes32" + } + ], + "internalType": "struct IIdlenessPhase.ProcessIdlenessParams[]", + "name": "_commands", + "type": "tuple[]" + } + ], + "name": "resolveTransactions", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_voteHash", + "type": "bytes32" + }, + { + "internalType": "enum ITransactions.VoteType", + "name": "_voteType", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "_otherExecutionFieldsHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_validatorIndex", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "_expectedAttemptId", + "type": "bytes32" + } + ], + "name": "revealVote", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_addressManager", + "type": "address" + } + ], + "name": "setAddressManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_expectedDecisionId", + "type": "uint256" + } + ], + "name": "submitAppeal", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_expectedDecisionId", + "type": "uint256" + } + ], + "name": "topUpAndProgressFinalization", + "outputs": [ + { + "internalType": "bool", + "name": "finalized", + "type": "bool" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_expectedDecisionId", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "leaderTimeunitsAllocation", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validatorTimeunitsAllocation", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "appealRounds", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "executionBudgetPerRound", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "executionConsumed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalMessageFees", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "rotations", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "maxPriceGenPerTimeUnit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "storageFeeMaxGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "receiptFeeMaxGasPrice", + "type": "uint256" + } + ], + "internalType": "struct IFeeManager.FeesDistribution", + "name": "", + "type": "tuple" + } + ], + "name": "topUpAndSubmitAppeal", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "leaderTimeunitsAllocation", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validatorTimeunitsAllocation", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "appealRounds", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "executionBudgetPerRound", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "executionConsumed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalMessageFees", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "rotations", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "maxPriceGenPerTimeUnit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "storageFeeMaxGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "receiptFeeMaxGasPrice", + "type": "uint256" + } + ], + "internalType": "struct IFeeManager.FeesDistribution", + "name": "_feesDistribution", + "type": "tuple" + } + ], + "name": "topUpFees", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferEthOnBehalf", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } ] diff --git a/genlayer_py/consensus/abi/rounds_storage_read_abi.json b/genlayer_py/consensus/abi/rounds_storage_read_abi.json new file mode 100644 index 0000000..5d84503 --- /dev/null +++ b/genlayer_py/consensus/abi/rounds_storage_read_abi.json @@ -0,0 +1,74 @@ +[ + { + "inputs": [ + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "round", + "type": "uint256" + } + ], + "name": "getValidatorVotes", + "outputs": [ + { + "internalType": "enum ITransactions.VoteType[]", + "name": "votes", + "type": "uint8[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "round", + "type": "uint256" + } + ], + "name": "getValidatorVotesHash", + "outputs": [ + { + "internalType": "bytes32[]", + "name": "hashes", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "round", + "type": "uint256" + } + ], + "name": "getValidatorResultHash", + "outputs": [ + { + "internalType": "bytes32[]", + "name": "hashes", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/genlayer_py/consensus/abi/transaction_manager_read_abi.json b/genlayer_py/consensus/abi/transaction_manager_read_abi.json new file mode 100644 index 0000000..fc059f2 --- /dev/null +++ b/genlayer_py/consensus/abi/transaction_manager_read_abi.json @@ -0,0 +1,40 @@ +[ + { + "inputs": [ + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + } + ], + "name": "getTxExecutionResult", + "outputs": [ + { + "internalType": "enum ITransactions.VoteType", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + } + ], + "name": "getNumOfInitialValidators", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/genlayer_py/consensus/consensus_main/decoder.py b/genlayer_py/consensus/consensus_main/decoder.py index b0fbea3..d2a62df 100644 --- a/genlayer_py/consensus/consensus_main/decoder.py +++ b/genlayer_py/consensus/consensus_main/decoder.py @@ -2,8 +2,11 @@ import rlp from web3 import Web3 from eth_abi import decode as abi_decode -from genlayer_py.consensus.abi import CONSENSUS_MAIN_ABI from genlayer_py.abi import calldata +from genlayer_py.consensus.consensus_main.legacy_abi import ( + LEGACY_ADD_TRANSACTION_ARGUMENT_TYPES, + LEGACY_ADD_TRANSACTION_SELECTOR, +) from genlayer_py.transactions.fees import ( ADD_TRANSACTION_WITH_FEES_ARGUMENT_TYPES, ADD_TRANSACTION_WITH_FEES_SELECTOR, @@ -24,10 +27,10 @@ def decode_add_transaction_data(encoded_data): ) return _format_fee_aware_add_transaction_data(abi_decoded[0]) - consensus_main_contract = w3.eth.contract(abi=CONSENSUS_MAIN_ABI) - contract_fn = consensus_main_contract.get_function_by_name("addTransaction") + if selector != LEGACY_ADD_TRANSACTION_SELECTOR: + raise ValueError(f"Unsupported addTransaction selector: 0x{selector}") abi_decoded = abi_decode( - contract_fn.argument_types, + LEGACY_ADD_TRANSACTION_ARGUMENT_TYPES, w3.to_bytes(hexstr=payload), ) encoded_tx_data_bytes = abi_decoded[4] @@ -64,8 +67,7 @@ def _format_fee_aware_add_transaction_data(params): "user_value": params[6], "fees_distribution": decode_fees_distribution_tuple(params[7]), "message_allocations": [ - decode_message_allocation_tuple(allocation) - for allocation in params[9] + decode_message_allocation_tuple(allocation) for allocation in params[9] ], } diff --git a/genlayer_py/consensus/consensus_main/encoder.py b/genlayer_py/consensus/consensus_main/encoder.py index 7332203..5df2b7f 100644 --- a/genlayer_py/consensus/consensus_main/encoder.py +++ b/genlayer_py/consensus/consensus_main/encoder.py @@ -7,8 +7,10 @@ from web3 import Web3 from eth_abi import encode as abi_encode from eth_typing import HexStr -import eth_utils -from genlayer_py.consensus.abi import CONSENSUS_MAIN_ABI +from genlayer_py.consensus.consensus_main.legacy_abi import ( + LEGACY_ADD_TRANSACTION_ARGUMENT_TYPES, + LEGACY_ADD_TRANSACTION_SELECTOR, +) from genlayer_py.transactions.fees import ( TransactionFeeOptions, encode_fee_aware_add_transaction_data, @@ -29,7 +31,6 @@ def encode_add_transaction_data( fee_aware: bool = False, ): w3 = Web3() - consensus_main_contract = w3.eth.contract(abi=CONSENSUS_MAIN_ABI) transaction_fees = normalize_transaction_fees(fees) if ( @@ -49,23 +50,20 @@ def encode_add_transaction_data( transaction_fees=transaction_fees, ) - contract_fn = consensus_main_contract.get_function_by_name("addTransaction") add_transaction_args = [ sender_address, recipient_address, num_of_initial_validators, max_rotations, w3.to_bytes(hexstr=tx_data), + valid_until, ] - if len(contract_fn.argument_types) >= 6: - add_transaction_args.append(valid_until) params = abi_encode( - contract_fn.argument_types, + LEGACY_ADD_TRANSACTION_ARGUMENT_TYPES, add_transaction_args, ) - function_selector = eth_utils.keccak(text=contract_fn.signature)[:4].hex() - encoded_data = "0x" + function_selector + params.hex() + encoded_data = "0x" + LEGACY_ADD_TRANSACTION_SELECTOR + params.hex() return encoded_data diff --git a/genlayer_py/consensus/consensus_main/legacy_abi.py b/genlayer_py/consensus/consensus_main/legacy_abi.py new file mode 100644 index 0000000..53f8171 --- /dev/null +++ b/genlayer_py/consensus/consensus_main/legacy_abi.py @@ -0,0 +1,23 @@ +"""Private codec constants for the pre-fee ConsensusMain call shape. + +The exported ConsensusMain ABI tracks the v0.6 train. These constants exist +only so the SDK can still decode or deliberately produce historical payloads +without letting an old selector leak back into the public contract surface. +""" + +import eth_utils + +LEGACY_ADD_TRANSACTION_ARGUMENT_TYPES = ( + "address", + "address", + "uint256", + "uint256", + "bytes", + "uint256", +) +LEGACY_ADD_TRANSACTION_SIGNATURE = ( + "addTransaction(address,address,uint256,uint256,bytes,uint256)" +) +LEGACY_ADD_TRANSACTION_SELECTOR = eth_utils.keccak( + text=LEGACY_ADD_TRANSACTION_SIGNATURE +)[:4].hex() diff --git a/genlayer_py/contracts/actions.py b/genlayer_py/contracts/actions.py index f2f62fc..96dfa64 100644 --- a/genlayer_py/contracts/actions.py +++ b/genlayer_py/contracts/actions.py @@ -14,7 +14,7 @@ from genlayer_py.exceptions import GenLayerError from genlayer_py.abi import calldata from genlayer_py.abi.transactions import serialize -from genlayer_py.chains import localnet +from genlayer_py.chains.utils import is_studio_chain from web3.constants import ADDRESS_ZERO from web3.logs import DISCARD from genlayer_py.contracts.utils import make_calldata_object @@ -24,6 +24,13 @@ FeesDistributionInput, FeesDistribution, FEES_DISTRIBUTION_ABI_TYPE, + DEFAULT_BOOTLOADER_OVERHEAD, + DEFAULT_CALLDATA_GAS_PER_BYTE, + DEFAULT_FIXED_PROPOSE_RECEIPT_GAS, + DEFAULT_GAS_PER_CHANGED_SLOT, + DEFAULT_INTRINSIC_GAS, + DEFAULT_RECEIPT_SLOTS_CHANGED, + MIN_RECEIPT_BYTES, NormalizedTransactionFees, SimulationFeeEstimateOptions, TransactionFeeEstimate, @@ -32,6 +39,7 @@ build_estimated_fees_options_from_simulation, calculate_local_round_fees, create_fees_distribution, + create_top_up_fees_distribution, encode_fee_aware_add_transaction_data, extract_studio_fee_policy, fees_distribution_to_abi_tuple, @@ -49,7 +57,7 @@ def get_contract_schema( self: GenLayerClient, address: Union[Address, ChecksumAddress], ) -> ContractSchema: - if self.chain.id != localnet.id: + if not is_studio_chain(self.chain): raise GenLayerError("Contract schema is not supported on this network") response = self.provider.make_request( @@ -62,10 +70,14 @@ def get_contract_schema_for_code( self: GenLayerClient, contract_code: AnyStr, ) -> ContractSchema: - if self.chain.id != localnet.id: + if not is_studio_chain(self.chain): raise GenLayerError("Contract schema is not supported on this network") - code_bytes = contract_code.encode("utf-8") if isinstance(contract_code, str) else contract_code + code_bytes = ( + contract_code.encode("utf-8") + if isinstance(contract_code, str) + else contract_code + ) response = self.provider.make_request( method="gen_getContractSchemaForCode", params=[eth_utils.hexadecimal.encode_hex(code_bytes)], @@ -86,7 +98,8 @@ def read_contract( ) -> CalldataEncodable: if account is None and self.local_account is None: raise GenLayerError("No account provided and no account is connected") - sender_address = self.local_account.address + sender = account if account is not None else self.local_account + sender_address = sender.address data = [ calldata.encode( make_calldata_object(method=function_name, args=args, kwargs=kwargs) @@ -214,26 +227,47 @@ def appeal_transaction( self: GenLayerClient, transaction_id: HexStr, account: Optional[LocalAccount] = None, - value: int = 0, + value: Optional[int] = None, + expected_decision_id: Optional[int] = None, ) -> HexStr: """Appeals a consensus transaction. Returns the original transaction_id. Appeals emit AppealStarted/TransactionActivated events (not NewTransaction), so we send the EVM tx directly instead of going through _send_transaction. + Both Studio and deployed Consensus bind the appeal to the exact active + decision and can resolve omitted decision/value inputs from the + authoritative appeal quote. The schedule-extending entry point is used for + every appeal because it accepts both pre-funded and unfunded next rounds; + ``submitAppeal`` rejects an unfunded next round before collecting its quoted + funding. """ sender_account = account if account is not None else self.local_account if sender_account is None: raise GenLayerError("No account set.") if self.chain.consensus_main_contract is None: raise GenLayerError("Consensus main contract not configured.") + expected_decision_id, resolved_value = _resolve_appeal_parameters( + self, + transaction_id, + expected_decision_id=expected_decision_id, + value=value, + ) - encoded_data = _encode_submit_appeal_data(self=self, transaction_id=transaction_id) + encoded_data = _encode_fee_management_data( + self=self, + function_name="topUpAndSubmitAppeal", + transaction_id=transaction_id, + # Consensus derives the appeal shape from live state. This normalized + # zero schedule exists only for ABI compatibility. + distribution={}, + expected_decision_id=expected_decision_id, + ) _send_consensus_call( self=self, encoded_data=encoded_data, sender_account=sender_account, - value=value, + value=resolved_value, operation_name="Appeal", ) @@ -244,13 +278,12 @@ def top_up_fees( self: GenLayerClient, transaction_id: HexStr, distribution: FeesDistributionInput, + value: int, account: Optional[LocalAccount] = None, - value: int = 0, ) -> HexStr: """Deposits additional fee budget for an existing consensus transaction. - Returns the backend RPC hash: an EVM transaction hash on network backends, - or the target GenLayer tx id on Studio/localnet. + Returns the signed EVM envelope hash on every backend. """ sender_account = account if account is not None else self.local_account encoded_data = _encode_fee_management_data( @@ -273,24 +306,33 @@ def top_up_and_submit_appeal( transaction_id: HexStr, distribution: FeesDistributionInput, account: Optional[LocalAccount] = None, - value: int = 0, + value: Optional[int] = None, + expected_decision_id: Optional[int] = None, ) -> HexStr: """Deposits appeal fee budget and submits an appeal in one consensus call. Returns the original GenLayer transaction id, matching appeal_transaction. + Both Studio and deployed Consensus use the decision-bound train shape. """ sender_account = account if account is not None else self.local_account + expected_decision_id, resolved_value = _resolve_appeal_parameters( + self, + transaction_id, + expected_decision_id=expected_decision_id, + value=value, + ) encoded_data = _encode_fee_management_data( self=self, function_name="topUpAndSubmitAppeal", transaction_id=transaction_id, distribution=distribution, + expected_decision_id=expected_decision_id, ) _send_consensus_call( self=self, encoded_data=encoded_data, sender_account=sender_account, - value=value, + value=resolved_value, operation_name="Top up and submit appeal", ) return transaction_id @@ -304,7 +346,9 @@ def get_round_number( if self.chain.rounds_storage_contract is None: raise GenLayerError("rounds_storage_contract not configured for this chain") contract = self.w3.eth.contract( - address=self.w3.to_checksum_address(self.chain.rounds_storage_contract["address"]), + address=self.w3.to_checksum_address( + self.chain.rounds_storage_contract["address"] + ), abi=self.chain.rounds_storage_contract["abi"], ) tx_bytes = _to_bytes32(self, transaction_id) @@ -320,7 +364,9 @@ def get_round_data( if self.chain.rounds_storage_contract is None: raise GenLayerError("rounds_storage_contract not configured for this chain") contract = self.w3.eth.contract( - address=self.w3.to_checksum_address(self.chain.rounds_storage_contract["address"]), + address=self.w3.to_checksum_address( + self.chain.rounds_storage_contract["address"] + ), abi=self.chain.rounds_storage_contract["abi"], ) tx_bytes = _to_bytes32(self, transaction_id) @@ -335,7 +381,9 @@ def get_last_round_data( if self.chain.rounds_storage_contract is None: raise GenLayerError("rounds_storage_contract not configured for this chain") contract = self.w3.eth.contract( - address=self.w3.to_checksum_address(self.chain.rounds_storage_contract["address"]), + address=self.w3.to_checksum_address( + self.chain.rounds_storage_contract["address"] + ), abi=self.chain.rounds_storage_contract["abi"], ) tx_bytes = _to_bytes32(self, transaction_id) @@ -345,36 +393,188 @@ def get_last_round_data( def can_appeal( self: GenLayerClient, transaction_id: HexStr, + expected_decision_id: Optional[int] = None, ) -> bool: - """Checks if a transaction can be appealed.""" + """Checks whether the exact active decision can be appealed on a network. + + When no decision id is supplied, the latest active decision is read first. + The guarded on-chain call returns ``False`` if that decision changes before + it is evaluated. Studio uses its lifecycle and appeal-quote RPCs for the + same semantics. + """ + if _is_studio_chain(self): + lifecycle = self.get_transaction_lifecycle(transaction_id) + if not lifecycle["decision_active"]: + return False + active_decision_id = lifecycle["decision_id"] + if ( + expected_decision_id is not None + and expected_decision_id != active_decision_id + ): + return False + try: + return get_appeal_quote(self, transaction_id)["decision_id"] == int( + active_decision_id + ) + except Exception as exc: + if "CanNotAppeal" in str(exc): + return False + raise + if self.chain.appeals_contract is None: raise GenLayerError("appeals_contract not configured for this chain") - contract = self.w3.eth.contract( - address=self.w3.to_checksum_address(self.chain.appeals_contract["address"]), - abi=self.chain.appeals_contract["abi"], - ) + if expected_decision_id is None: + expected_decision_id = _get_active_decision_id(self, transaction_id) + if expected_decision_id is None: + return False + contract = _appeals_contract(self) tx_bytes = _to_bytes32(self, transaction_id) - return contract.functions.canAppeal(tx_bytes).call() + return contract.functions.canAppeal(tx_bytes, expected_decision_id).call() + + +def get_appeal_quote( + self: GenLayerClient, + transaction_id: HexStr, +) -> Dict[str, int]: + """Returns the exact latest-decision appeal charge and race guard. + + ``total`` is the value to submit: the appeal bond plus induced-work + funding. Pass ``decision_id`` back to the decision-guarded appeal methods. + """ + if _is_studio_chain(self): + response = self.provider.make_request( + method="gen_estimateLatestAppealCharge", + params=[{"txId": transaction_id}], + ) + if not isinstance(response, dict): + raise GenLayerError( + "gen_estimateLatestAppealCharge returned an invalid response" + ) + if response.get("error") is not None: + raise GenLayerError( + f"gen_estimateLatestAppealCharge failed: {response['error']}" + ) + quote = response.get("result") + if not isinstance(quote, dict): + raise GenLayerError( + "gen_estimateLatestAppealCharge returned an invalid result" + ) + decision_id = int(quote["decisionId"]) + bond = int(quote["bond"]) + funding = int(quote["funding"]) + return { + "decision_id": decision_id, + "bond": bond, + "funding": funding, + "total": bond + funding, + "appeal_deadline": int(quote["appealDeadline"]), + } + contract = _consensus_data_contract(self) + decision_id, bond, funding, appeal_deadline = ( + contract.functions.estimateLatestAppealCharge( + _to_bytes32(self, transaction_id) + ).call() + ) + return { + "decision_id": int(decision_id), + "bond": int(bond), + "funding": int(funding), + "total": int(bond) + int(funding), + "appeal_deadline": int(appeal_deadline), + } + + +def get_appeal_charge( + self: GenLayerClient, + transaction_id: HexStr, +) -> int: + """Returns the full payment required to appeal the latest decision.""" + return get_appeal_quote(self, transaction_id)["total"] def get_min_appeal_bond( self: GenLayerClient, transaction_id: HexStr, ) -> int: - """Calculates the minimum bond required to appeal a transaction.""" - if self.chain.fee_manager_contract is None or self.chain.rounds_storage_contract is None: - raise GenLayerError("fee_manager_contract/rounds_storage_contract not configured for this chain") + """Deprecated alias for :func:`get_appeal_charge`. - round_number = get_round_number(self, transaction_id) - tx = self.get_transaction(transaction_id) - tx_status = int(tx["status"]) + Despite its historical name, this returns bond plus induced-work funding. + """ + return get_appeal_charge(self, transaction_id) - fee_contract = self.w3.eth.contract( - address=self.w3.to_checksum_address(self.chain.fee_manager_contract["address"]), - abi=self.chain.fee_manager_contract["abi"], + +def _consensus_data_contract(self: GenLayerClient): + if self.chain.consensus_data_contract is None: + raise GenLayerError("consensus_data_contract not configured for this chain") + return self.w3.eth.contract( + address=self.w3.to_checksum_address( + self.chain.consensus_data_contract["address"] + ), + abi=self.chain.consensus_data_contract["abi"], ) - tx_bytes = _to_bytes32(self, transaction_id) - return fee_contract.functions.calculateMinAppealBond(tx_bytes, round_number, tx_status).call() + + +def _appeals_contract(self: GenLayerClient): + if self.chain.appeals_contract is None: + raise GenLayerError("appeals_contract not configured for this chain") + return self.w3.eth.contract( + address=self.w3.to_checksum_address(self.chain.appeals_contract["address"]), + abi=self.chain.appeals_contract["abi"], + ) + + +def _get_active_decision_id( + self: GenLayerClient, + transaction_id: HexStr, +) -> Optional[int]: + lifecycle = ( + _consensus_data_contract(self) + .functions.getTransactionLifecycle(_to_bytes32(self, transaction_id), 0) + .call() + ) + latest_decision = lifecycle[2] + decision_active = lifecycle[3] + return int(latest_decision[1]) if decision_active else None + + +def _resolve_appeal_parameters( + self: GenLayerClient, + transaction_id: HexStr, + expected_decision_id: Optional[int], + value: Optional[int], +) -> tuple[int, int]: + if expected_decision_id is not None and value is not None: + return expected_decision_id, value + + try: + quote = get_appeal_quote(self, transaction_id) + except Exception as exc: + raise GenLayerError( + "Cannot quote an active appeal decision. The transaction may not be " + "appealable yet; refresh its lifecycle and retry." + ) from exc + + if ( + expected_decision_id is not None + and expected_decision_id != quote["decision_id"] + ): + raise GenLayerError( + f"Appeal decision {expected_decision_id} is stale; the latest active " + f"decision is {quote['decision_id']}. Refresh and retry." + ) + + return ( + quote["decision_id"] if expected_decision_id is None else expected_decision_id, + quote["total"] if value is None else value, + ) + + +def _is_studio_chain(self: GenLayerClient) -> bool: + """Reports whether the client targets the studio-embedded consensus. + + This includes local Studio, the stable hosted Studio, and preview Studio. + """ + return is_studio_chain(self.chain) def _to_bytes32(self: GenLayerClient, hex_str: HexStr) -> bytes: @@ -397,8 +597,8 @@ def simulate_write_contract( sim_config: Optional[SimConfig] = None, transaction_hash_variant: TransactionHashVariant = TransactionHashVariant.LATEST_NONFINAL, ) -> dict: - if self.chain.id != localnet.id: - raise GenLayerError("Client is not connected to the localnet") + if not is_studio_chain(self.chain): + raise GenLayerError("Simulation is only supported on Studio networks") if account is None and self.local_account is None: raise GenLayerError("No account provided and no account is connected") sender_address = self.local_account.address if account is None else account.address @@ -442,13 +642,27 @@ def _transaction_fees_to_rpc( } if normalized["fee_value"] is not None: rpc_fees["feeValue"] = normalized["fee_value"] - return rpc_fees + return _json_safe_rpc_value(rpc_fees) + + +def _json_safe_rpc_value(value): + if isinstance(value, (bytes, bytearray)): + return "0x" + bytes(value).hex() + if isinstance(value, list): + return [_json_safe_rpc_value(item) for item in value] + if isinstance(value, tuple): + return [_json_safe_rpc_value(item) for item in value] + if isinstance(value, dict): + return {key: _json_safe_rpc_value(item) for key, item in value.items()} + return value def _encode_submit_appeal_data( self: GenLayerClient, transaction_id: HexStr, + expected_decision_id: Optional[int] = None, ): + """Encode the decision-bound submitAppeal entrypoint.""" consensus_main_contract = self.w3.eth.contract( abi=self.chain.consensus_main_contract["abi"] ) @@ -457,16 +671,21 @@ def _encode_submit_appeal_data( transaction_id = transaction_id[2:] if len(transaction_id) > 64: raise ValueError("transaction_id too long for bytes32") - params = abi_encode( - contract_fn.argument_types, - [self.w3.to_bytes(hexstr=transaction_id)], - ) + if expected_decision_id is None: + raise ValueError("submitAppeal requires expected_decision_id") + arguments = [self.w3.to_bytes(hexstr=transaction_id), expected_decision_id] + params = abi_encode(contract_fn.argument_types, arguments) function_selector = eth_utils.keccak(text=contract_fn.signature)[:4].hex() encoded_data = "0x" + function_selector + params.hex() return encoded_data FEE_MANAGEMENT_ARGUMENT_TYPES = ("bytes32", FEES_DISTRIBUTION_ABI_TYPE) +TOP_UP_AND_SUBMIT_APPEAL_ARGUMENT_TYPES = ( + "bytes32", + "uint256", + FEES_DISTRIBUTION_ABI_TYPE, +) def _encode_fee_management_data( @@ -474,20 +693,31 @@ def _encode_fee_management_data( function_name: str, transaction_id: HexStr, distribution: FeesDistributionInput, + expected_decision_id: Optional[int] = None, ): + """Encode the chain's native fee-management entrypoint.""" if function_name not in ("topUpFees", "topUpAndSubmitAppeal"): raise ValueError(f"Unsupported fee management function: {function_name}") tx_bytes = _to_bytes32(self, transaction_id) - fees_distribution = create_fees_distribution(distribution) - params = abi_encode( - FEE_MANAGEMENT_ARGUMENT_TYPES, - [ - tx_bytes, - fees_distribution_to_abi_tuple(fees_distribution), - ], + fees_distribution = ( + create_top_up_fees_distribution(distribution) + if function_name == "topUpFees" + else create_fees_distribution(distribution) ) - signature = f"{function_name}(bytes32,{FEES_DISTRIBUTION_ABI_TYPE})" + fees_tuple = fees_distribution_to_abi_tuple(fees_distribution) + if function_name == "topUpAndSubmitAppeal": + if expected_decision_id is None: + raise ValueError("topUpAndSubmitAppeal requires expected_decision_id") + argument_types = TOP_UP_AND_SUBMIT_APPEAL_ARGUMENT_TYPES + arguments = [tx_bytes, expected_decision_id, fees_tuple] + signature = f"{function_name}(bytes32,uint256,{FEES_DISTRIBUTION_ABI_TYPE})" + else: + argument_types = FEE_MANAGEMENT_ARGUMENT_TYPES + arguments = [tx_bytes, fees_tuple] + signature = f"{function_name}(bytes32,{FEES_DISTRIBUTION_ABI_TYPE})" + + params = abi_encode(argument_types, arguments) function_selector = eth_utils.keccak(text=signature)[:4].hex() return "0x" + function_selector + params.hex() @@ -575,27 +805,51 @@ def _get_default_valid_until() -> int: def get_current_fee_policy(self: GenLayerClient) -> FeePolicyQuote: - if self.chain.fee_manager_contract and self.chain.fee_manager_contract.get("address"): + if self.chain.fee_manager_contract and self.chain.fee_manager_contract.get( + "address" + ): fee_manager_contract = self.w3.eth.contract( - address=self.w3.to_checksum_address(self.chain.fee_manager_contract["address"]), + address=self.w3.to_checksum_address( + self.chain.fee_manager_contract["address"] + ), abi=FEE_MANAGER_CALCULATE_ROUND_FEES_ABI, ) gen_per_time_unit = fee_manager_contract.functions.GENPerTimeUnit().call() storage_unit_price = fee_manager_contract.functions.storageUnitPrice().call() - receipt_gas_price = fee_manager_contract.functions.quoteGasPrice().call() + quoted_receipt_gas_price = fee_manager_contract.functions.quoteGasPrice().call() execution_budget_floor = ( fee_manager_contract.functions.messageFeeParamsBudgetFloor().call() ) + enabled = ( + gen_per_time_unit > 0 + or storage_unit_price > 0 + or quoted_receipt_gas_price > 0 + ) + network_receipt_gas_price = self.w3.eth.gas_price if enabled else 0 + receipt_gas_price = max(quoted_receipt_gas_price, network_receipt_gas_price) + if enabled and receipt_gas_price == 0: + raise GenLayerError( + "receipt gas price quoted as zero; refusing to build a zero price cap" + ) + local_execution_budget_floor = receipt_gas_price * ( + DEFAULT_FIXED_PROPOSE_RECEIPT_GAS + + DEFAULT_INTRINSIC_GAS + + DEFAULT_BOOTLOADER_OVERHEAD + + (MIN_RECEIPT_BYTES * DEFAULT_CALLDATA_GAS_PER_BYTE) + + (DEFAULT_RECEIPT_SLOTS_CHANGED * DEFAULT_GAS_PER_CHANGED_SLOT) + ) return { - "enabled": ( - gen_per_time_unit > 0 - or storage_unit_price > 0 - or receipt_gas_price > 0 - ), + "enabled": enabled, "genPerTimeUnit": gen_per_time_unit, "storageUnitPrice": storage_unit_price, "receiptGasPrice": receipt_gas_price, - "executionBudgetFloor": execution_budget_floor, + "executionBudgetFloor": max( + execution_budget_floor, + local_execution_budget_floor, + ), + # Live networks quote through FeeManager.calculateRoundFees; this + # field is only consumed by Studio's local mirror. + "timeUnitOverlayBps": 0, } try: @@ -616,7 +870,11 @@ def estimate_fees_distribution( options: Optional[FeeEstimateOptions] = None, ) -> FeesDistribution: policy = get_current_fee_policy(self) - return build_estimated_fees_distribution(options, policy) + return build_estimated_fees_distribution( + options, + policy, + self.chain.default_consensus_max_rotations, + ) def estimate_transaction_fees( @@ -632,11 +890,19 @@ def _estimate_transaction_fees_with_policy( options: Optional[FeeEstimateOptions], policy: FeePolicyQuote, ) -> TransactionFeeEstimate: - distribution = build_estimated_fees_distribution(options, policy) + distribution = build_estimated_fees_distribution( + options, + policy, + self.chain.default_consensus_max_rotations, + ) - if self.chain.fee_manager_contract and self.chain.fee_manager_contract.get("address"): + if self.chain.fee_manager_contract and self.chain.fee_manager_contract.get( + "address" + ): fee_manager_contract = self.w3.eth.contract( - address=self.w3.to_checksum_address(self.chain.fee_manager_contract["address"]), + address=self.w3.to_checksum_address( + self.chain.fee_manager_contract["address"] + ), abi=FEE_MANAGER_CALCULATE_ROUND_FEES_ABI, ) round_fees = fee_manager_contract.functions.calculateRoundFees( @@ -705,8 +971,10 @@ def estimate_transaction_fees_for_write( sim_config: Optional[SimConfig] = None, transaction_hash_variant: TransactionHashVariant = TransactionHashVariant.LATEST_NONFINAL, ) -> TransactionFeeEstimate: - if self.chain.id != localnet.id: - raise GenLayerError("Target write fee estimation is only supported on localnet") + if not is_studio_chain(self.chain): + raise GenLayerError( + "Target write fee estimation is only supported on Studio networks" + ) if account is None and self.local_account is None: raise GenLayerError("No account provided and no account is connected") @@ -769,14 +1037,17 @@ def _resolve_transaction_fees( num_of_initial_validators: int, ) -> NormalizedTransactionFees: transaction_fees = normalize_transaction_fees(fees) - if ( - transaction_fees["fee_value"] is not None - or not requires_fee_deposit_calculation(transaction_fees["distribution"]) + if transaction_fees[ + "fee_value" + ] is not None or not requires_fee_deposit_calculation( + transaction_fees["distribution"] ): transaction_fees["fee_value"] = transaction_fees["fee_value"] or 0 return transaction_fees - if not self.chain.fee_manager_contract or not self.chain.fee_manager_contract.get("address"): + if not self.chain.fee_manager_contract or not self.chain.fee_manager_contract.get( + "address" + ): try: policy = get_current_fee_policy(self) except GenLayerError as exc: @@ -824,7 +1095,9 @@ def _encode_add_transaction_data( abi=self.chain.consensus_main_contract["abi"] ) contract_fn = consensus_main_contract.get_function_by_name("addTransaction") - abi_version = _get_add_transaction_abi_version(self.chain.consensus_main_contract["abi"]) + abi_version = _get_add_transaction_abi_version( + self.chain.consensus_main_contract["abi"] + ) transaction_fees = transaction_fees or normalize_transaction_fees() use_fee_aware_transaction = ( transaction_fees["requires_fee_aware_transaction"] or abi_version == "fees" @@ -876,7 +1149,7 @@ def _prepare_transaction( nonce = self.get_current_nonce(address=sender) - if self.chain.id != localnet.id: + if not is_studio_chain(self.chain): latest_block = self.w3.eth.get_block("latest") base_fee = latest_block["baseFeePerGas"] priority_fee = self.w3.to_wei(2, "gwei") @@ -905,6 +1178,63 @@ def _prepare_transaction( return transaction +KNOWN_REVERT_SELECTOR_NAMES = { + "0x8d53e553": "InsufficientFees", + "0xb4132db3": "MaxPriceExceeded", + "0x57df8523": "ExecutionBudgetExceeded", + "0x305e533c": "BudgetTooLow", + "0xa70732ee": "RollupBudgetBelowFloor", + "0x632be5a1": "FeeValueMustBeNonZero", +} + + +def _format_rpc_error(error: Exception) -> str: + parts = [str(error)] + for attr in ("message", "data"): + value = getattr(error, attr, None) + if isinstance(value, str) and value.strip(): + parts.append(value) + args = getattr(error, "args", ()) + for arg in args: + if isinstance(arg, dict): + for key in ("message", "data", "details", "shortMessage"): + value = arg.get(key) + if isinstance(value, str) and value.strip(): + parts.append(value) + elif isinstance(arg, str) and arg.strip(): + parts.append(arg) + + text = " ".join(dict.fromkeys(parts)) + selector_name = next( + ( + name + for selector, name in KNOWN_REVERT_SELECTOR_NAMES.items() + if selector in text + ), + None, + ) + if selector_name and selector_name not in text: + return f"{text} ({selector_name})" + return text + + +def _receipt_revert_reason(self: GenLayerClient, tx_hash: HexStr) -> Optional[str]: + """Read Studio's additive receipt reason without weakening EVM semantics.""" + try: + response = self.provider.make_request( + method="eth_getTransactionReceipt", params=[tx_hash] + ) + except Exception: + return None + if not isinstance(response, dict): + return None + receipt = response.get("result") + if not isinstance(receipt, dict): + return None + reason = receipt.get("revertReason") or receipt.get("error") + return reason if isinstance(reason, str) and reason.strip() else None + + def _send_consensus_call( self: GenLayerClient, encoded_data: HexStr, @@ -919,25 +1249,29 @@ def _send_consensus_call( if self.chain.consensus_main_contract is None: raise GenLayerError("Consensus main contract not configured.") - transaction = _prepare_transaction( - self=self, - sender=sender_account.address, - recipient=self.chain.consensus_main_contract["address"], - data=encoded_data, - value=value, - ) - signed_transaction = sender_account.sign_transaction(transaction) - serialized_transaction = self.w3.to_hex(signed_transaction.raw_transaction) - tx_hash = self.provider.make_request( - method="eth_sendRawTransaction", params=[serialized_transaction] - )["result"] - if self.chain.id == localnet.id: - return tx_hash - + try: + transaction = _prepare_transaction( + self=self, + sender=sender_account.address, + recipient=self.chain.consensus_main_contract["address"], + data=encoded_data, + value=value, + ) + signed_transaction = sender_account.sign_transaction(transaction) + serialized_transaction = self.w3.to_hex(signed_transaction.raw_transaction) + tx_hash = self.provider.make_request( + method="eth_sendRawTransaction", params=[serialized_transaction] + )["result"] + except Exception as exc: + raise GenLayerError( + f"{operation_name} failed: {_format_rpc_error(exc)}" + ) from exc tx_receipt = self.w3.eth.wait_for_transaction_receipt(tx_hash) if tx_receipt.status != 1: - raise GenLayerError(f"{operation_name} reverted: EVM tx {tx_hash}") + reason = _receipt_revert_reason(self, tx_hash) + suffix = f". {reason}" if reason else "" + raise GenLayerError(f"{operation_name} reverted: EVM tx {tx_hash}{suffix}") return tx_hash @@ -956,30 +1290,35 @@ def _send_transaction( if self.chain.consensus_main_contract is None: raise GenLayerError( - f"Consensus main contract address not found in chain config for \"{self.chain.name}\".", + f'Consensus main contract address not found in chain config for "{self.chain.name}".', ) - transaction = _prepare_transaction( - self=self, - sender=sender_account.address, - recipient=self.chain.consensus_main_contract["address"], - data=encoded_data, - value=value, - ) - signed_transaction = sender_account.sign_transaction(transaction) - serialized_transaction = self.w3.to_hex(signed_transaction.raw_transaction) - params = [serialized_transaction] - if sim_config is not None: - params.append(sim_config) - tx_hash = self.provider.make_request( - method="eth_sendRawTransaction", params=params - )["result"] + try: + transaction = _prepare_transaction( + self=self, + sender=sender_account.address, + recipient=self.chain.consensus_main_contract["address"], + data=encoded_data, + value=value, + ) + signed_transaction = sender_account.sign_transaction(transaction) + serialized_transaction = self.w3.to_hex(signed_transaction.raw_transaction) + params = [serialized_transaction] + if sim_config is not None: + params.append(sim_config) + tx_hash = self.provider.make_request( + method="eth_sendRawTransaction", params=params + )["result"] + except Exception as exc: + raise GenLayerError(f"Transaction failed: {_format_rpc_error(exc)}") from exc tx_receipt = self.w3.eth.wait_for_transaction_receipt(tx_hash) if tx_receipt.status != 1: + reason = _receipt_revert_reason(self, tx_hash) + suffix = f" {reason}" if reason else "" raise GenLayerError( f"Transaction reverted: EVM tx {tx_hash} to consensus contract " - f"{self.chain.consensus_main_contract['address']} was reverted." + f"{self.chain.consensus_main_contract['address']} was reverted.{suffix}" ) consensus_main_contract = self.w3.eth.contract( diff --git a/genlayer_py/contracts/utils.py b/genlayer_py/contracts/utils.py index 7e79432..2f02317 100644 --- a/genlayer_py/contracts/utils.py +++ b/genlayer_py/contracts/utils.py @@ -9,7 +9,7 @@ def make_calldata_object( ) -> CalldataEncodable: ret: Dict[str, CalldataEncodable] = {} if method is not None: - ret["method"] = method + ret[""] = method if args is not None and len(args) > 0: ret["args"] = args if kwargs is not None and isinstance(kwargs, dict) and kwargs: diff --git a/genlayer_py/staking/__init__.py b/genlayer_py/staking/__init__.py index 8c8fa92..c6de75f 100644 --- a/genlayer_py/staking/__init__.py +++ b/genlayer_py/staking/__init__.py @@ -5,6 +5,12 @@ validator_claim, validator_prime, set_operator, + get_validator_join_context, + get_operator_transfer_context, + initiate_operator_transfer, + complete_operator_transfer, + cancel_operator_transfer, + get_pending_operator, set_identity, delegator_join, delegator_exit, @@ -12,6 +18,8 @@ epoch, active_validators, active_validators_count, + joined_validators, + joined_validators_count, is_validator, get_validator_info, get_stake_info, @@ -19,6 +27,16 @@ validator_min_stake, delegator_min_stake, ) +from genlayer_py.staking.operator_registration import ( + OperatorPublicKey, + OperatorRegistrationContext, + OperatorRegistrationProof, + create_operator_registration, + operator_address_from_public_key, + operator_possession_message, + operator_public_key_from_private_key, + verify_operator_registration, +) __all__ = [ "validator_join", @@ -27,6 +45,12 @@ "validator_claim", "validator_prime", "set_operator", + "get_validator_join_context", + "get_operator_transfer_context", + "initiate_operator_transfer", + "complete_operator_transfer", + "cancel_operator_transfer", + "get_pending_operator", "set_identity", "delegator_join", "delegator_exit", @@ -34,10 +58,20 @@ "epoch", "active_validators", "active_validators_count", + "joined_validators", + "joined_validators_count", "is_validator", "get_validator_info", "get_stake_info", "banned_validators", "validator_min_stake", "delegator_min_stake", + "OperatorPublicKey", + "OperatorRegistrationContext", + "OperatorRegistrationProof", + "create_operator_registration", + "operator_address_from_public_key", + "operator_possession_message", + "operator_public_key_from_private_key", + "verify_operator_registration", ] diff --git a/genlayer_py/staking/abi/staking_abi.json b/genlayer_py/staking/abi/staking_abi.json index fba7fd3..51dbdc5 100644 --- a/genlayer_py/staking/abi/staking_abi.json +++ b/genlayer_py/staking/abi/staking_abi.json @@ -1,4033 +1,6668 @@ [ - { - "inputs": [], - "name": "BurnTransferFailed", - "type": "error" - }, - { - "inputs": [], - "name": "DeepthoughtCallFailed", - "type": "error" - }, - { - "inputs": [], - "name": "DelegatorBelowMinimumStake", - "type": "error" - }, - { - "inputs": [], - "name": "DelegatorExitExceedsShares", - "type": "error" - }, - { - "inputs": [], - "name": "DelegatorExitWouldBeBelowMinimum", - "type": "error" - }, - { - "inputs": [], - "name": "DelegatorMayNotExitWithZeroShares", - "type": "error" - }, - { - "inputs": [], - "name": "DelegatorMayNotJoinTwoValidatorsSimultaneously", - "type": "error" - }, - { - "inputs": [], - "name": "DelegatorMayNotJoinWithZeroValue", - "type": "error" - }, - { - "inputs": [], - "name": "DelegatorMustExitAllWhenBelowMinimum", - "type": "error" - }, - { - "inputs": [], - "name": "EpochAdvanceNotReady", - "type": "error" - }, - { - "inputs": [], - "name": "EpochAlreadyFinalized", - "type": "error" - }, - { - "inputs": [], - "name": "EpochNotFinalized", - "type": "error" - }, - { - "inputs": [], - "name": "EpochNotFinished", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "FailedTransfer", - "type": "error" - }, - { - "inputs": [], - "name": "InflationAlreadyInitialized", - "type": "error" - }, - { - "inputs": [], - "name": "InflationAlreadyReceived", - "type": "error" - }, - { - "inputs": [], - "name": "InflationInvalidAmount", - "type": "error" - }, - { - "inputs": [], - "name": "InflationRequestFailed", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientInflationFunds", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidAtEpoch", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidInflationThresholds", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidOperatorAddress", - "type": "error" - }, - { - "inputs": [], - "name": "MaxNumberOfValidatorsReached", - "type": "error" - }, - { - "inputs": [], - "name": "MaxValidatorsCannotBeZero", - "type": "error" - }, - { - "inputs": [], - "name": "NFTMinterCallFailed", - "type": "error" - }, - { - "inputs": [], - "name": "NFTMinterNotConfigured", - "type": "error" - }, - { - "inputs": [], - "name": "NoBurning", - "type": "error" - }, - { - "inputs": [], - "name": "NumberOfValidatorsExceedsAvailable", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyGEN", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyIdleness", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyIdlenessOrTribunal", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyTransactions", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyTransactionsOrTribunal", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyTribunal", - "type": "error" - }, - { - "inputs": [], - "name": "OperatorAlreadyAssigned", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "epoch", - "type": "uint256" - } - ], - "name": "PendingTribunals", - "type": "error" - }, - { - "inputs": [], - "name": "PreviousEpochNotFinalizable", - "type": "error" - }, - { - "inputs": [], - "name": "ReductionFactorCannotBeZero", - "type": "error" - }, - { - "inputs": [], - "name": "ValidatorAlreadyInTree", - "type": "error" - }, - { - "inputs": [], - "name": "ValidatorAlreadyJoined", - "type": "error" - }, - { - "inputs": [], - "name": "ValidatorBelowMinimumStake", - "type": "error" - }, - { - "inputs": [], - "name": "ValidatorExitExceedsShares", - "type": "error" - }, - { - "inputs": [], - "name": "ValidatorMayNotBeDelegator", - "type": "error" - }, - { - "inputs": [], - "name": "ValidatorMayNotDepositZeroValue", - "type": "error" - }, - { - "inputs": [], - "name": "ValidatorMayNotJoinWithZeroValue", - "type": "error" - }, - { - "inputs": [], - "name": "ValidatorMustNotBeDelegator", - "type": "error" - }, - { - "inputs": [], - "name": "ValidatorNotActive", - "type": "error" - }, - { - "inputs": [], - "name": "ValidatorNotInTree", - "type": "error" - }, - { - "inputs": [], - "name": "ValidatorNotJoined", - "type": "error" - }, - { - "inputs": [], - "name": "ValidatorWithdrawalExceedsStake", - "type": "error" - }, - { - "inputs": [], - "name": "ValidatorsConsumed", - "type": "error" - }, - { - "inputs": [], - "name": "ValidatorsUnavailable", - "type": "error" - }, - { - "anonymous": false, - "inputs": [], - "name": "AllValidatorBansRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "BurnFailed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "BurnToL1", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "delegator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "DelegatorClaim", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "delegator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "DelegatorExit", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "delegator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "DelegatorJoin", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "epoch", - "type": "uint256" - } - ], - "name": "EpochAdvance", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "epoch", - "type": "uint256" - } - ], - "name": "EpochFinalize", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "epoch", - "type": "uint256" - } - ], - "name": "EpochHasPendingTribunals", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "timestamp", - "type": "uint256" - } - ], - "name": "EpochZeroEnded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FeesReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "timestamp", - "type": "uint256" - } - ], - "name": "InflationInitiated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "epoch", - "type": "uint256" - } - ], - "name": "InflationReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "targetEpoch", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "l2GasPrice", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "l2GasLimit", - "type": "uint256" - } - ], - "name": "InflationRequestedFromL2", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "inflationRequestThreshold", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "inflationTargetAhead", - "type": "uint256" - } - ], - "name": "InflationThresholdsSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "l2GasPrice", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "l2GasLimit", - "type": "uint256" - } - ], - "name": "L1InflationGasParamsSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "processedCount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "nextIndex", - "type": "uint256" - } - ], - "name": "QuarantinesCleanedUp", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "deepthought", - "type": "address" - } - ], - "name": "SetDeepthought", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "delegatorMinStake", - "type": "uint256" - } - ], - "name": "SetDelegatorMinimumStake", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "epochExtraMinDuration", - "type": "uint256" - } - ], - "name": "SetEpochExtraMinDuration", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "epochMinDuration", - "type": "uint256" - } - ], - "name": "SetEpochMinDuration", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "epochMinDurationThreshold", - "type": "uint256" - } - ], - "name": "SetEpochMinDurationThreshold", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "epochZeroMinDuration", - "type": "uint256" - } - ], - "name": "SetEpochZeroMinDuration", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "gen", - "type": "address" - } - ], - "name": "SetGen", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "maxValidators", - "type": "uint256" - } - ], - "name": "SetMaxValidators", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "reductionFactor", - "type": "uint256" - } - ], - "name": "SetReductionFactor", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "stakingInvariant", - "type": "address" - } - ], - "name": "SetStakingInvariant", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "transactionFeesManager", - "type": "address" - } - ], - "name": "SetTransactionFeesManager", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "delegatorUnbondingPeriod", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "validatorUnbondingPeriod", - "type": "uint256" - } - ], - "name": "SetUnbondingPeriods", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "validatorMinStake", - "type": "uint256" - } - ], - "name": "SetValidatorMinimumStake", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "alpha", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "beta", - "type": "uint256" - } - ], - "name": "SetValidatorWeightParams", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "ValidatorBanRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "ValidatorBannedDeterministic", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "bannedAt", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "bannedUntil", - "type": "uint256" - } - ], - "name": "ValidatorBannedIdleness", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "ValidatorClaim", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "ValidatorDeposit", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "ValidatorExit", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "ValidatorIsAlreadyInTree", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "ValidatorIsNotActive", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "ValidatorIsNotInTree", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "ValidatorJoin", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "epoch", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "validatorRewards", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "delegatorRewards", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "feeRewards", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "feePenalties", - "type": "uint256" - } - ], - "name": "ValidatorPrime", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "ValidatorQuarantineRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "ValidatorQuarantineRepealed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "quarantinedAt", - "type": "uint256" - } - ], - "name": "ValidatorQuarantined", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "validatorSlashing", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "delegatorSlashing", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "epoch", - "type": "uint256" - } - ], - "name": "ValidatorSlash", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "count", - "type": "uint256" - } - ], - "name": "ValidatorsRegistered", - "type": "event" - }, - { - "inputs": [], - "name": "BASE_TOKEN", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "DEFAULT_DELEGATOR_MIN_STAKE", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "DEFAULT_VALIDATOR_MIN_STAKE", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "DELEGATOR_UNBONDING_PERIOD", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "INFLATION_BASE", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "INFLATION_DEEPTHOUGHT_BPS", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "INFLATION_DEVELOPER_BPS", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "INFLATION_FINAL", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "INFLATION_INITIAL", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "INFLATION_MID", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "INFLATION_STAKER_BPS", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "INFLATION_STEEPNESS", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "INFLATION_VALIDATOR_BPS", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "QUARANTINE_MANAGER_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VALIDATOR_UNBONDING_PERIOD", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "activeValidators", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "activeValidatorsCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "activeWeights", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "addressManager", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "validatorAddresses", - "type": "address[]" - } - ], - "name": "adminRegisterValidators", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "burning", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "canAdvance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "deepthought", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_inflation", - "type": "uint256" - } - ], - "name": "deepthoughtInflation", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_delegator", - "type": "address" - }, - { - "internalType": "address", - "name": "_validator", - "type": "address" - } - ], - "name": "delegatorClaim", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_delegator", - "type": "address" - }, - { - "internalType": "address", - "name": "_validator", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_index", - "type": "uint256" - } - ], - "name": "delegatorDeposit", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "quantity", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "commit", - "type": "uint256" - } - ], - "internalType": "struct IGenLayerStaking.Claim", - "name": "claim_", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "input", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "output", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "epoch", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkToNextCommit", - "type": "uint256" - } - ], - "internalType": "struct IGenLayerStaking.Commit", - "name": "commit_", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_delegator", - "type": "address" - }, - { - "internalType": "address", - "name": "_validator", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_epoch", - "type": "uint256" - } - ], - "name": "delegatorDepositByEpoch", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "input", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "output", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "epoch", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkToNextCommit", - "type": "uint256" - } - ], - "internalType": "struct IGenLayerStaking.Commit", - "name": "commit_", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_delegator", - "type": "address" - }, - { - "internalType": "address", - "name": "_validator", - "type": "address" - } - ], - "name": "delegatorDepositLen", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_validator", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "delegatorExit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_validator", - "type": "address" - } - ], - "name": "delegatorJoin", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "delegatorMinStake", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_delegator", - "type": "address" - }, - { - "internalType": "address", - "name": "_validator", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_index", - "type": "uint256" - } - ], - "name": "delegatorWithdrawal", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "quantity", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "commit", - "type": "uint256" - } - ], - "internalType": "struct IGenLayerStaking.Claim", - "name": "claim_", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "input", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "output", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "epoch", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkToNextCommit", - "type": "uint256" - } - ], - "internalType": "struct IGenLayerStaking.Commit", - "name": "commit_", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_delegator", - "type": "address" - }, - { - "internalType": "address", - "name": "_validator", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_epoch", - "type": "uint256" - } - ], - "name": "delegatorWithdrawalByEpoch", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "input", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "output", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "epoch", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkToNextCommit", - "type": "uint256" - } - ], - "internalType": "struct IGenLayerStaking.Commit", - "name": "commit_", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_delegator", - "type": "address" - }, - { - "internalType": "address", - "name": "_validator", - "type": "address" - } - ], - "name": "delegatorWithdrawalLen", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_inflation", - "type": "uint256" - } - ], - "name": "developerInflation", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "epoch", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "epochAdvance", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "epochEven", - "outputs": [ - { - "internalType": "uint256", - "name": "start", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "end", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "inflation", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "weight", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "weightDeposit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "weightWithdrawal", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "vcount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "claimed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "stakeDeposit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "stakeWithdrawal", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "slashed", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "epochExtraMinDuration", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "epochFinalize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "epochFinalizeImmediate", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_epoch", - "type": "uint256" - } - ], - "name": "epochInflation", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "epochMinDuration", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "epochMinDurationThreshold", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "epochOdd", - "outputs": [ - { - "internalType": "uint256", - "name": "start", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "end", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "inflation", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "weight", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "weightDeposit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "weightWithdrawal", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "vcount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "claimed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "stakeDeposit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "stakeWithdrawal", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "slashed", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "epochZeroMinDuration", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "finalizationPhaseAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "finalized", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_randomSeed", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_txCreatedTimestamp", - "type": "uint256" - } - ], - "name": "getActivatorForSeed", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_size", - "type": "uint256" - } - ], - "name": "getAllBannedValidators", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "internalType": "uint256", - "name": "untilEpochBanned", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "permanentlyBanned", - "type": "bool" - } - ], - "internalType": "struct IGenLayerStaking.BannedValidators[]", - "name": "validatorList", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_epoch", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_size", - "type": "uint256" - } - ], - "name": "getAllBannedValidatorsForEpoch", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "internalType": "uint256", - "name": "untilEpochBanned", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "permanentlyBanned", - "type": "bool" - } - ], - "internalType": "struct IGenLayerStaking.BannedValidators[]", - "name": "validatorList", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_size", - "type": "uint256" - } - ], - "name": "getAllQuarantinedValidators", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "internalType": "uint256", - "name": "untilEpochBanned", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "permanentlyBanned", - "type": "bool" - } - ], - "internalType": "struct IGenLayerStaking.BannedValidators[]", - "name": "validatorList", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_epoch", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_size", - "type": "uint256" - } - ], - "name": "getAllQuarantinedValidatorsForEpoch", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "internalType": "uint256", - "name": "untilEpochBanned", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "permanentlyBanned", - "type": "bool" - } - ], - "internalType": "struct IGenLayerStaking.BannedValidators[]", - "name": "validatorList", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_delegator", - "type": "address" - }, - { - "internalType": "address", - "name": "_validator", - "type": "address" - } - ], - "name": "getPendingDelegatorDeposits", - "outputs": [ - { - "internalType": "uint256", - "name": "total", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_delegator", - "type": "address" - }, - { - "internalType": "address", - "name": "_validator", - "type": "address" - } - ], - "name": "getPendingDelegatorWithdrawals", - "outputs": [ - { - "internalType": "uint256", - "name": "total", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_validator", - "type": "address" - } - ], - "name": "getPendingValidatorDeposits", - "outputs": [ - { - "internalType": "uint256", - "name": "total", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_validator", - "type": "address" - } - ], - "name": "getPendingValidatorWithdrawals", - "outputs": [ - { - "internalType": "uint256", - "name": "total", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_validator", - "type": "address" - } - ], - "name": "getValidatorDelegators", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_validator", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_pageSize", - "type": "uint256" - } - ], - "name": "getValidatorDelegatorsInfo", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "delegator", - "type": "address" - }, - { - "internalType": "uint256", - "name": "currentStake", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "currentShares", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "pendingDeposits", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "pendingWithdrawals", - "type": "uint256" - } - ], - "internalType": "struct IGenLayerStaking.DelegatorInfo[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_validator", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_pageSize", - "type": "uint256" - } - ], - "name": "getValidatorDelegatorsPaginated", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getValidatorQuarantineList", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_pageSize", - "type": "uint256" - } - ], - "name": "getValidatorsJoined", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_validator", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_at", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_until", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - } - ], - "name": "idlenessBan", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "_validators", - "type": "address[]" - }, - { - "internalType": "uint256", - "name": "_quarantinedAt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_quarantinedUntil", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - } - ], - "name": "idlenessBanBatch", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "idlenessPhaseAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "inflationEpoch", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_inflationOnset", - "type": "uint256" - } - ], - "name": "inflationInit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_epoch", - "type": "uint256" - } - ], - "name": "inflationReceive", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "inflationRequestThreshold", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "inflationSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "inflationTargetAhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_validator", - "type": "address" - }, - { - "internalType": "address", - "name": "_delegator", - "type": "address" - } - ], - "name": "isDelegatorOfValidator", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_validator", - "type": "address" - } - ], - "name": "isValidator", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_validator", - "type": "address" - } - ], - "name": "isValidatorBanned", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l2GasLimit", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l2GasPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "maxValidators", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "operator", - "type": "address" - } - ], - "name": "operatorsToValidators", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "reductionFactor", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "removeAllValidatorBans", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_validator", - "type": "address" - } - ], - "name": "removeValidatorBan", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "revealingPhaseAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "_deepthought", - "type": "address" - } - ], - "name": "setDeepthought", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_delegatorMinStake", - "type": "uint256" - } - ], - "name": "setDelegatorMinimumStake", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_epochExtraMinDuration", - "type": "uint256" - } - ], - "name": "setEpochExtraMinDuration", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_epochMinDuration", - "type": "uint256" - } - ], - "name": "setEpochMinDuration", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_epochMinDurationThreshold", - "type": "uint256" - } - ], - "name": "setEpochMinDurationThreshold", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_epochZeroMinDuration", - "type": "uint256" - } - ], - "name": "setEpochZeroMinDuration", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_finalizationPhase", - "type": "address" - } - ], - "name": "setFinalizationPhase", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_gen", - "type": "address" - } - ], - "name": "setGen", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_idlenessPhase", - "type": "address" - } - ], - "name": "setIdlenessPhase", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_inflationRequestThreshold", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_inflationTargetAhead", - "type": "uint256" - } - ], - "name": "setInflationThresholds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_l2GasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_l2GasLimit", - "type": "uint256" - } - ], - "name": "setL1InflationGasParams", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_maxValidators", - "type": "uint256" - } - ], - "name": "setMaxValidators", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_reductionFactor", - "type": "uint256" - } - ], - "name": "setReductionFactor", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_revealingPhase", - "type": "address" - } - ], - "name": "setRevealingPhase", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_stakingInvariant", - "type": "address" - } - ], - "name": "setStakingInvariant", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_transactionFeesManager", - "type": "address" - } - ], - "name": "setTransactionFeesManager", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_delegatorUnbondingPeriod", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_validatorUnbondingPeriod", - "type": "uint256" - } - ], - "name": "setUnbondingPeriods", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_validatorMinStake", - "type": "uint256" - } - ], - "name": "setValidatorMinimumStake", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_alpha", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_beta", - "type": "uint256" - } - ], - "name": "setValidatorWeightParams", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_delegator", - "type": "address" - }, - { - "internalType": "address", - "name": "_validator", - "type": "address" - } - ], - "name": "sharesOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_delegator", - "type": "address" - }, - { - "internalType": "address", - "name": "_validator", - "type": "address" - } - ], - "name": "stakeOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "stakingInvariant", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "transactionFeesManager", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_validator", - "type": "address" - } - ], - "name": "validatorBanDeterministic", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_validator", - "type": "address" - } - ], - "name": "validatorBanned", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "internalType": "uint256", - "name": "untilEpochBanned", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "permanentlyBanned", - "type": "bool" - } - ], - "internalType": "struct IGenLayerStaking.BannedValidators", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_validator", - "type": "address" - } - ], - "name": "validatorClaim", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_validator", - "type": "address" - } - ], - "name": "validatorDelegatorCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_validator", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_index", - "type": "uint256" - } - ], - "name": "validatorDeposit", - "outputs": [ - { - "internalType": "uint256", - "name": "epoch_", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "input", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "output", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "epoch", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkToNextCommit", - "type": "uint256" - } - ], - "internalType": "struct IGenLayerStaking.Commit", - "name": "commit_", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "validatorDeposit", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_validator", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_epoch", - "type": "uint256" - } - ], - "name": "validatorDepositByEpoch", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "input", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "output", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "epoch", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkToNextCommit", - "type": "uint256" - } - ], - "internalType": "struct IGenLayerStaking.Commit", - "name": "commit_", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_validator", - "type": "address" - } - ], - "name": "validatorDepositLen", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "validatorExit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_operator", - "type": "address" - } - ], - "name": "validatorJoin", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "validatorJoin", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "validatorMinStake", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_validator", - "type": "address" - } - ], - "name": "validatorPrime", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_validator", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_at", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - } - ], - "name": "validatorQuarantine", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "validatorQuarantineCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_validator", - "type": "address" - } - ], - "name": "validatorQuarantineRepeal", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_seed", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_slot", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_epoch", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_txCreatedTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_number", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "_weighted", - "type": "bool" - }, - { - "internalType": "address[]", - "name": "_consumed", - "type": "address[]" - } - ], - "name": "validatorSelection", - "outputs": [ - { - "internalType": "uint256", - "name": "leader_", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "validators_", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "penalized_", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_seed", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_slot", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_txCreatedTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_number", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "_weighted", - "type": "bool" - }, - { - "internalType": "address[]", - "name": "_consumed", - "type": "address[]" - } - ], - "name": "validatorSelection", - "outputs": [ - { - "internalType": "uint256", - "name": "leader_", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "validators_", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "penalized_", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_validator", - "type": "address" - } - ], - "name": "validatorView", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "left", - "type": "address" - }, - { - "internalType": "address", - "name": "right", - "type": "address" - }, - { - "internalType": "address", - "name": "parent", - "type": "address" - }, - { - "internalType": "uint256", - "name": "eBanned", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "ePrimed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "vStake", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "vShares", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "dStake", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "dShares", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "vDeposit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "vWithdrawal", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "live", - "type": "bool" - } - ], - "internalType": "struct IGenLayerStaking.ValidatorView", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_validator", - "type": "address" - } - ], - "name": "validatorViewPrePrimed", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "left", - "type": "address" - }, - { - "internalType": "address", - "name": "right", - "type": "address" - }, - { - "internalType": "address", - "name": "parent", - "type": "address" - }, - { - "internalType": "uint256", - "name": "eBanned", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "ePrimed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "vStake", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "vShares", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "dStake", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "dShares", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "vDeposit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "vWithdrawal", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "live", - "type": "bool" - } - ], - "internalType": "struct IGenLayerStaking.ValidatorView", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_validator", - "type": "address" - } - ], - "name": "validatorViewPrimed", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "left", - "type": "address" - }, - { - "internalType": "address", - "name": "right", - "type": "address" - }, - { - "internalType": "address", - "name": "parent", - "type": "address" - }, - { - "internalType": "uint256", - "name": "eBanned", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "ePrimed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "vStake", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "vShares", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "dStake", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "dShares", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "vDeposit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "vWithdrawal", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "live", - "type": "bool" - } - ], - "internalType": "struct IGenLayerStaking.ValidatorView", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_validator", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_index", - "type": "uint256" - } - ], - "name": "validatorWithdrawal", - "outputs": [ - { - "internalType": "uint256", - "name": "epoch_", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "input", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "output", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "epoch", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkToNextCommit", - "type": "uint256" - } - ], - "internalType": "struct IGenLayerStaking.Commit", - "name": "commit_", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_validator", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_epoch", - "type": "uint256" - } - ], - "name": "validatorWithdrawalByEpoch", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "input", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "output", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "epoch", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkToNextCommit", - "type": "uint256" - } - ], - "internalType": "struct IGenLayerStaking.Commit", - "name": "commit_", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_validator", - "type": "address" - } - ], - "name": "validatorWithdrawalLen", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "validatorsCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - } - ], - "name": "validatorsEven", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - } - ], - "name": "validatorsJoined", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "validatorsJoinedCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - } - ], - "name": "validatorsOdd", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "validatorsRoot", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - } - ], - "name": "weightsEven", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - } - ], - "name": "weightsOdd", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } + { + "inputs": [], + "name": "ArrayLengthMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "BurnTransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "DeepthoughtCallFailed", + "type": "error" + }, + { + "inputs": [], + "name": "DelegatorBelowMinimumStake", + "type": "error" + }, + { + "inputs": [], + "name": "DelegatorExitExceedsShares", + "type": "error" + }, + { + "inputs": [], + "name": "DelegatorExitUnrepresentableShares", + "type": "error" + }, + { + "inputs": [], + "name": "DelegatorExitWouldBeBelowMinimum", + "type": "error" + }, + { + "inputs": [], + "name": "DelegatorMayNotExitWithZeroShares", + "type": "error" + }, + { + "inputs": [], + "name": "DelegatorMayNotJoinTwoValidatorsSimultaneously", + "type": "error" + }, + { + "inputs": [], + "name": "DelegatorMayNotJoinWithZeroValue", + "type": "error" + }, + { + "inputs": [], + "name": "DelegatorMustExitAllWhenBelowMinimum", + "type": "error" + }, + { + "inputs": [], + "name": "EpochAdvanceNotReady", + "type": "error" + }, + { + "inputs": [], + "name": "EpochAlreadyFinalized", + "type": "error" + }, + { + "inputs": [], + "name": "EpochDurationCannotBeZero", + "type": "error" + }, + { + "inputs": [], + "name": "EpochDurationOverflow", + "type": "error" + }, + { + "inputs": [], + "name": "EpochNotFinalized", + "type": "error" + }, + { + "inputs": [], + "name": "EpochNotFinished", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "FailedTransfer", + "type": "error" + }, + { + "inputs": [], + "name": "IncentivePercentageTooHigh", + "type": "error" + }, + { + "inputs": [], + "name": "InflationAlreadyInitialized", + "type": "error" + }, + { + "inputs": [], + "name": "InflationAlreadyReceived", + "type": "error" + }, + { + "inputs": [], + "name": "InflationInvalidAmount", + "type": "error" + }, + { + "inputs": [], + "name": "InflationRequestFailed", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientInflationFunds", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidAtEpoch", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInflationThresholds", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidOperatorAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPageSize", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPrimingSelfStakeBps", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidWeightParams", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "JudicialCapacityReservationActive", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "JudicialCapacityReservationMissing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "JudicialQuarantineCauseActive", + "type": "error" + }, + { + "inputs": [], + "name": "MaxNumberOfValidatorsReached", + "type": "error" + }, + { + "inputs": [], + "name": "MaxValidatorsCannotBeZero", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requested", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maximum", + "type": "uint256" + } + ], + "name": "MaxValidatorsExceedsSafeLimit", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "attemptId", + "type": "uint64" + } + ], + "name": "MinimumStakeTransitionActive", + "type": "error" + }, + { + "inputs": [], + "name": "MinimumStakeTransitionConfigLocked", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint24", + "name": "expectedCursor", + "type": "uint24" + }, + { + "internalType": "uint24", + "name": "actualCursor", + "type": "uint24" + } + ], + "name": "MinimumStakeTransitionCursorMismatch", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "expectedAttemptId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "actualAttemptId", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "expectedAttemptHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "actualAttemptHash", + "type": "bytes32" + } + ], + "name": "MinimumStakeTransitionIdentityMismatch", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "enum IGenLayerStaking.MinimumStakeTransitionStatus", + "name": "status", + "type": "uint8" + } + ], + "name": "MinimumStakeTransitionInvalidStatus", + "type": "error" + }, + { + "inputs": [], + "name": "MinimumStakeTransitionNotActive", + "type": "error" + }, + { + "inputs": [], + "name": "MirrorFieldOverflow", + "type": "error" + }, + { + "inputs": [], + "name": "NFTMinterCallFailed", + "type": "error" + }, + { + "inputs": [], + "name": "NFTMinterNotConfigured", + "type": "error" + }, + { + "inputs": [], + "name": "NoBurning", + "type": "error" + }, + { + "inputs": [], + "name": "NumberOfValidatorsExceedsAvailable", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyGEN", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyIdleness", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyIdlenessOrTribunal", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyStakingRouter", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyTransactions", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyTransactionsOrTribunal", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyTribunal", + "type": "error" + }, + { + "inputs": [], + "name": "OperatorAlreadyAssigned", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + } + ], + "name": "PendingTribunals", + "type": "error" + }, + { + "inputs": [], + "name": "PermanentQuarantineNeedsOwnerPardon", + "type": "error" + }, + { + "inputs": [], + "name": "PreviousEpochNotFinalizable", + "type": "error" + }, + { + "inputs": [], + "name": "ReductionFactorCannotBeZero", + "type": "error" + }, + { + "inputs": [], + "name": "RegistryFull", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + } + ], + "name": "SelectionAuthorityPinned", + "type": "error" + }, + { + "inputs": [], + "name": "UnauthorizedDelegatorClaim", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requested", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "cap", + "type": "uint256" + } + ], + "name": "UnbanCapExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "ValidatorAlreadyInTree", + "type": "error" + }, + { + "inputs": [], + "name": "ValidatorAlreadyJoined", + "type": "error" + }, + { + "inputs": [], + "name": "ValidatorBelowMinimumStake", + "type": "error" + }, + { + "inputs": [], + "name": "ValidatorDoesNotExist", + "type": "error" + }, + { + "inputs": [], + "name": "ValidatorExitExceedsShares", + "type": "error" + }, + { + "inputs": [], + "name": "ValidatorMayNotBeDelegator", + "type": "error" + }, + { + "inputs": [], + "name": "ValidatorMayNotDepositZeroValue", + "type": "error" + }, + { + "inputs": [], + "name": "ValidatorMayNotJoinWithZeroValue", + "type": "error" + }, + { + "inputs": [], + "name": "ValidatorMustNotBeDelegator", + "type": "error" + }, + { + "inputs": [], + "name": "ValidatorNotActive", + "type": "error" + }, + { + "inputs": [], + "name": "ValidatorNotInTree", + "type": "error" + }, + { + "inputs": [], + "name": "ValidatorNotJoined", + "type": "error" + }, + { + "inputs": [], + "name": "ValidatorWithdrawalExceedsStake", + "type": "error" + }, + { + "inputs": [], + "name": "ValidatorsConsumed", + "type": "error" + }, + { + "inputs": [], + "name": "ValidatorsUnavailable", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newVStake", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bool", + "name": "recordX", + "type": "bool" + } + ], + "name": "AdminStakeCorrected", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "AllValidatorBansRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum IGenLayerStaking.BurnSource", + "name": "source", + "type": "uint8" + } + ], + "name": "BurnAccrued", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "burnThreshold", + "type": "uint256" + } + ], + "name": "BurnThresholdSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "BurnToL1", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "epochNumber", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "priorWeight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "epochWeight", + "type": "uint256" + } + ], + "name": "CorruptedEpochWeight", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "DelegationToBelowMinimumValidator", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "DelegatorClaim", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "DelegatorExit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "DelegatorJoin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + } + ], + "name": "EpochAdvance", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + } + ], + "name": "EpochFinalize", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FeesReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "incentivePercentage", + "type": "uint256" + } + ], + "name": "IncentivePercentageSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "InflationInitiated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + } + ], + "name": "InflationReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "targetEpoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "l2GasPrice", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "l2GasLimit", + "type": "uint256" + } + ], + "name": "InflationRequestedFromL2", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "inflationRequestThreshold", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "inflationTargetAhead", + "type": "uint256" + } + ], + "name": "InflationThresholdsSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "restored", + "type": "bool" + } + ], + "name": "JudicialCapacityReleased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "JudicialCapacityReserved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + } + ], + "name": "JudicialConvictionMaterialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + } + ], + "name": "JudicialConvictionQueued", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "JudicialSuspensionSettled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "accusedAtEpoch", + "type": "uint256" + } + ], + "name": "JudiciallySuspended", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "l2GasPrice", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "l2GasLimit", + "type": "uint256" + } + ], + "name": "L1InflationGasParamsSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "maxPerEpoch", + "type": "uint256" + } + ], + "name": "MaxUnbansPerEpochSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "processedCount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "nextIndex", + "type": "uint256" + } + ], + "name": "QuarantinesCleanedUp", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "count", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "snapshotHash", + "type": "bytes32" + } + ], + "name": "SelectionPoolSnapshotSealed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "daoFeeBps", + "type": "uint256" + } + ], + "name": "SetDaoFeeBps", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "deepthought", + "type": "address" + } + ], + "name": "SetDeepthought", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "delegatorMinStake", + "type": "uint256" + } + ], + "name": "SetDelegatorMinimumStake", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "enabled", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "epochExtraMinDuration", + "type": "uint256" + } + ], + "name": "SetEpochExtraMinDurationOverride", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "epochMinDuration", + "type": "uint256" + } + ], + "name": "SetEpochMinDuration", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "epochMinDurationThreshold", + "type": "uint256" + } + ], + "name": "SetEpochMinDurationThreshold", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "epochZeroMinDuration", + "type": "uint256" + } + ], + "name": "SetEpochZeroMinDuration", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "gen", + "type": "address" + } + ], + "name": "SetGen", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "maxValidators", + "type": "uint256" + } + ], + "name": "SetMaxValidators", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "bps", + "type": "uint256" + } + ], + "name": "SetPrimingSelfStakeBps", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "reductionFactor", + "type": "uint256" + } + ], + "name": "SetReductionFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "transactionFeesManager", + "type": "address" + } + ], + "name": "SetTransactionFeesManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "delegatorUnbondingPeriod", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "validatorUnbondingPeriod", + "type": "uint256" + } + ], + "name": "SetUnbondingPeriods", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "validatorMinStake", + "type": "uint256" + } + ], + "name": "SetValidatorMinimumStake", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "alpha", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "beta", + "type": "uint256" + } + ], + "name": "SetValidatorWeightParams", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "SharelessFeesBurned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "SharelessStakeZeroed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "removed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remaining", + "type": "uint256" + } + ], + "name": "TemporaryValidatorBansRemovalProgress", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "ValidatorBanRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "bannedAt", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "bannedUntil", + "type": "uint256" + } + ], + "name": "ValidatorBannedIdleness", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ValidatorClaim", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ValidatorDeposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ValidatorExit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ValidatorFeePenaltyBurned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ValidatorJoin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "attemptId", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "attemptHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldMinimum", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposedMinimum", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint24", + "name": "worksetCount", + "type": "uint24" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "worksetHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "baseGeneration", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "candidateGeneration", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "targetEpoch", + "type": "uint256" + } + ], + "name": "ValidatorMinimumStakeTransitionBegun", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "attemptId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint24", + "name": "oldCursor", + "type": "uint24" + }, + { + "indexed": false, + "internalType": "uint24", + "name": "newCursor", + "type": "uint24" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "candidateWrites", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "revision", + "type": "uint64" + } + ], + "name": "ValidatorMinimumStakeTransitionProgressed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "attemptId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "enum IGenLayerStaking.MinimumStakeTransitionStatus", + "name": "status", + "type": "uint8" + } + ], + "name": "ValidatorMinimumStakeTransitionStatusUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "validatorRewards", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "delegatorRewards", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeRewards", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feePenalties", + "type": "uint256" + } + ], + "name": "ValidatorPrime", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "ValidatorQuarantineRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "quarantinedAt", + "type": "uint256" + } + ], + "name": "ValidatorQuarantined", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ValidatorSelfStakeBonus", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "validatorSlashing", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "delegatorSlashing", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + } + ], + "name": "ValidatorSlash", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "predicted", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "actual", + "type": "uint256" + } + ], + "name": "VcountShadowMismatch", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "epochNumber", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "maxWeight", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "weightWithdrawal", + "type": "uint256" + } + ], + "name": "WeightWithdrawalOverflow", + "type": "event" + }, + { + "inputs": [], + "name": "BASE_TOKEN", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DEFAULT_DELEGATOR_MIN_STAKE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DEFAULT_VALIDATOR_MIN_STAKE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DELEGATOR_UNBONDING_PERIOD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INFLATION_BASE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INFLATION_DEEPTHOUGHT_BPS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INFLATION_DEVELOPER_BPS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INFLATION_FINAL", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INFLATION_INITIAL", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INFLATION_MID", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INFLATION_STAKER_BPS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INFLATION_STEEPNESS", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INFLATION_VALIDATOR_BPS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "QUARANTINE_MANAGER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VALIDATOR_UNBONDING_PERIOD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "enum IGenLayerStaking.BurnSource", + "name": "source", + "type": "uint8" + } + ], + "name": "accrueBurn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "addressManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_validatorMinStake", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "_expectedPublishedVersion", + "type": "uint64" + } + ], + "name": "beginValidatorMinimumStakeTransition", + "outputs": [ + { + "internalType": "uint64", + "name": "attemptId", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "attemptHash", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "burnThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "burnedDevInflationSurplus", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "burnedStrandedFees", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "burning", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "canAdvance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "canFinalize", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "_attemptId", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "_attemptHash", + "type": "bytes32" + } + ], + "name": "cancelValidatorMinimumStakeTransition", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "clearEpochExtraMinDurationOverride", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + } + ], + "name": "convictJudicially", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "daoFeeBps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "deepthought", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_inflation", + "type": "uint256" + } + ], + "name": "deepthoughtInflation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_delegator", + "type": "address" + }, + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "delegatorClaim", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_delegator", + "type": "address" + }, + { + "internalType": "address", + "name": "_validator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_index", + "type": "uint256" + } + ], + "name": "delegatorDeposit", + "outputs": [ + { + "components": [ + { + "internalType": "uint120", + "name": "quantity", + "type": "uint120" + }, + { + "internalType": "uint120", + "name": "offset", + "type": "uint120" + }, + { + "internalType": "uint256", + "name": "commit", + "type": "uint256" + } + ], + "internalType": "struct IGenLayerStaking.Claim", + "name": "claim_", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "input", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "output", + "type": "uint256" + }, + { + "internalType": "uint120", + "name": "outstanding", + "type": "uint120" + }, + { + "internalType": "uint64", + "name": "epoch", + "type": "uint64" + }, + { + "internalType": "uint56", + "name": "linkToNextCommit", + "type": "uint56" + }, + { + "internalType": "bool", + "name": "priced", + "type": "bool" + }, + { + "internalType": "bool", + "name": "fragmented", + "type": "bool" + } + ], + "internalType": "struct IGenLayerStaking.Commit", + "name": "commit_", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_delegator", + "type": "address" + }, + { + "internalType": "address", + "name": "_validator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + } + ], + "name": "delegatorDepositByEpoch", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "input", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "output", + "type": "uint256" + }, + { + "internalType": "uint120", + "name": "outstanding", + "type": "uint120" + }, + { + "internalType": "uint64", + "name": "epoch", + "type": "uint64" + }, + { + "internalType": "uint56", + "name": "linkToNextCommit", + "type": "uint56" + }, + { + "internalType": "bool", + "name": "priced", + "type": "bool" + }, + { + "internalType": "bool", + "name": "fragmented", + "type": "bool" + } + ], + "internalType": "struct IGenLayerStaking.Commit", + "name": "commit_", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_delegator", + "type": "address" + }, + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "delegatorDepositLen", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "delegatorExit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "delegatorJoin", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "delegatorMinStake", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_delegator", + "type": "address" + }, + { + "internalType": "address", + "name": "_validator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_index", + "type": "uint256" + } + ], + "name": "delegatorWithdrawal", + "outputs": [ + { + "components": [ + { + "internalType": "uint120", + "name": "quantity", + "type": "uint120" + }, + { + "internalType": "uint120", + "name": "offset", + "type": "uint120" + }, + { + "internalType": "uint256", + "name": "commit", + "type": "uint256" + } + ], + "internalType": "struct IGenLayerStaking.Claim", + "name": "claim_", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "input", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "output", + "type": "uint256" + }, + { + "internalType": "uint120", + "name": "outstanding", + "type": "uint120" + }, + { + "internalType": "uint64", + "name": "epoch", + "type": "uint64" + }, + { + "internalType": "uint56", + "name": "linkToNextCommit", + "type": "uint56" + }, + { + "internalType": "bool", + "name": "priced", + "type": "bool" + }, + { + "internalType": "bool", + "name": "fragmented", + "type": "bool" + } + ], + "internalType": "struct IGenLayerStaking.Commit", + "name": "commit_", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_delegator", + "type": "address" + }, + { + "internalType": "address", + "name": "_validator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + } + ], + "name": "delegatorWithdrawalByEpoch", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "input", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "output", + "type": "uint256" + }, + { + "internalType": "uint120", + "name": "outstanding", + "type": "uint120" + }, + { + "internalType": "uint64", + "name": "epoch", + "type": "uint64" + }, + { + "internalType": "uint56", + "name": "linkToNextCommit", + "type": "uint56" + }, + { + "internalType": "bool", + "name": "priced", + "type": "bool" + }, + { + "internalType": "bool", + "name": "fragmented", + "type": "bool" + } + ], + "internalType": "struct IGenLayerStaking.Commit", + "name": "commit_", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_delegator", + "type": "address" + }, + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "delegatorWithdrawalLen", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_inflation", + "type": "uint256" + } + ], + "name": "developerInflation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "economicEpochValidatorCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "effectiveValidatorOccupancy", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "seed", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "slot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "number", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "count", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "generation", + "type": "uint64" + }, + { + "internalType": "address", + "name": "pointer", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "runtimeCodeHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "snapshotHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "maxUtil", + "type": "uint256" + }, + { + "internalType": "uint256[7]", + "name": "temporaryUnavailableBits", + "type": "uint256[7]" + }, + { + "internalType": "uint256[]", + "name": "consumedRegistryIndexes", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "priorSlotPenalizedRegistryIndexes", + "type": "uint256[]" + } + ], + "internalType": "struct IGenLayerStaking.SnapshotSelectionRequest", + "name": "_request", + "type": "tuple" + } + ], + "name": "eligibleRegistryIndexesFromSnapshotAuthority", + "outputs": [ + { + "internalType": "uint256[]", + "name": "indexes", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "epoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "epochAdvance", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "epochEven", + "outputs": [ + { + "internalType": "uint256", + "name": "start", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "end", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "inflation", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "weightDeposit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "weightWithdrawal", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vcount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "claimed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "stakeDeposit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "stakeWithdrawal", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "slashed", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "epochExtraMinDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "epochExtraMinDurationOverride", + "outputs": [ + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "epochFinalize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "epochFinalizeImmediate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + } + ], + "name": "epochInflation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "epochMinDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "epochMinDurationThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "epochOdd", + "outputs": [ + { + "internalType": "uint256", + "name": "start", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "end", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "inflation", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "weight", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "weightDeposit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "weightWithdrawal", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vcount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "claimed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "stakeDeposit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "stakeWithdrawal", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "slashed", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "epochZeroMinDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "expectedClaimableInflation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "seed", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "slot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "number", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "count", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "generation", + "type": "uint64" + }, + { + "internalType": "address", + "name": "pointer", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "runtimeCodeHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "snapshotHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "maxUtil", + "type": "uint256" + }, + { + "internalType": "uint256[7]", + "name": "temporaryUnavailableBits", + "type": "uint256[7]" + }, + { + "internalType": "uint256[]", + "name": "consumedRegistryIndexes", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "priorSlotPenalizedRegistryIndexes", + "type": "uint256[]" + } + ], + "internalType": "struct IGenLayerStaking.SnapshotSelectionRequest", + "name": "_request", + "type": "tuple" + }, + { + "internalType": "uint256[]", + "name": "_candidateIndexes", + "type": "uint256[]" + } + ], + "name": "filterEligibleRegistryIndexesFromSnapshotAuthority", + "outputs": [ + { + "internalType": "uint256[]", + "name": "indexes", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "finalizationPhaseAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "_attemptId", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "_attemptHash", + "type": "bytes32" + } + ], + "name": "finalizeValidatorMinimumStakeTransition", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "finalized", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_randomSeed", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_txCreatedTimestamp", + "type": "uint256" + } + ], + "name": "getActivatorForSeed", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_size", + "type": "uint256" + } + ], + "name": "getAllBannedValidators", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "untilEpochBanned", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "permanentlyBanned", + "type": "bool" + } + ], + "internalType": "struct IGenLayerStaking.BannedValidators[]", + "name": "validatorList", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_size", + "type": "uint256" + } + ], + "name": "getAllBannedValidatorsForEpoch", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "untilEpochBanned", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "permanentlyBanned", + "type": "bool" + } + ], + "internalType": "struct IGenLayerStaking.BannedValidators[]", + "name": "validatorList", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_size", + "type": "uint256" + } + ], + "name": "getAllQuarantinedValidators", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "untilEpochBanned", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "permanentlyBanned", + "type": "bool" + } + ], + "internalType": "struct IGenLayerStaking.BannedValidators[]", + "name": "validatorList", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_size", + "type": "uint256" + } + ], + "name": "getAllQuarantinedValidatorsForEpoch", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "untilEpochBanned", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "permanentlyBanned", + "type": "bool" + } + ], + "internalType": "struct IGenLayerStaking.BannedValidators[]", + "name": "validatorList", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getEpochExtraMinDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_delegator", + "type": "address" + }, + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "getPendingDelegatorDeposits", + "outputs": [ + { + "internalType": "uint256", + "name": "total", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_delegator", + "type": "address" + }, + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "getPendingDelegatorWithdrawals", + "outputs": [ + { + "internalType": "uint256", + "name": "total", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_maxItems", + "type": "uint256" + } + ], + "name": "getPendingJudicialConvictions", + "outputs": [ + { + "internalType": "address[]", + "name": "validators", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "getPendingValidatorDeposits", + "outputs": [ + { + "internalType": "uint256", + "name": "total", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "getPendingValidatorWithdrawals", + "outputs": [ + { + "internalType": "uint256", + "name": "total", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_txCreatedTimestamp", + "type": "uint256" + } + ], + "name": "getUnavailableQuarantinedValidators", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "getValidatorDelegators", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_pageSize", + "type": "uint256" + } + ], + "name": "getValidatorDelegatorsInfo", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentStake", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "currentShares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "pendingDeposits", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "pendingWithdrawals", + "type": "uint256" + } + ], + "internalType": "struct IGenLayerStaking.DelegatorInfo[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_pageSize", + "type": "uint256" + } + ], + "name": "getValidatorDelegatorsPaginated", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getValidatorQuarantineList", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_pageSize", + "type": "uint256" + } + ], + "name": "getValidatorsJoined", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_at", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_until", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + } + ], + "name": "idlenessBan", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_validators", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "_quarantinedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_quarantinedUntil", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + } + ], + "name": "idlenessBanBatch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "idlenessPhaseAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "_registryIndexes", + "type": "uint256[]" + } + ], + "name": "idlenessRestrictionEndEpochs", + "outputs": [ + { + "internalType": "uint256[]", + "name": "endEpochs", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "incentivePercentage", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "inflationEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epochTo", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_inauguralTimestamp", + "type": "uint256" + } + ], + "name": "inflationInit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "inflationInitDone", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + } + ], + "name": "inflationReceive", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "inflationRequestThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + } + ], + "name": "inflationRequested", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "inflationSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "inflationTargetAhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_inauguralTimestamp", + "type": "uint256" + } + ], + "name": "initializeEpochStart", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + }, + { + "internalType": "address", + "name": "_delegator", + "type": "address" + } + ], + "name": "isDelegatorOfValidator", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_index", + "type": "uint256" + } + ], + "name": "isSelectableValidatorAtRegistryIndex", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_index", + "type": "uint256" + } + ], + "name": "isTribunalVoterLiveAvailableAtRegistryIndex", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "isValidator", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "isValidatorBanned", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "judicialCapacityReservationCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "judicialCapacityReserved", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "judicialConvictionPending", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "judicialSelectionRestricted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "judicialSelectionRestrictedCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "judicialSelectionRestrictionVersion", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "judicialSuspended", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2GasLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2GasPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxUnbansPerEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxValidators", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "operatorsToValidators", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingJudicialConvictionCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingRequestInflationFromL1", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "permanentRestrictionVersion", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "registryIndex", + "type": "uint256" + } + ], + "name": "preparedEconomicCohortContains", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "preparedEconomicCohortCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "preparedSelectionRosterCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "primingSelfStakeBps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "_attemptId", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "_attemptHash", + "type": "bytes32" + }, + { + "internalType": "uint24", + "name": "_expectedCursor", + "type": "uint24" + } + ], + "name": "processValidatorMinimumStakeTransition", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "quarantineHistoryVersion", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + } + ], + "name": "recountVcount", + "outputs": [ + { + "internalType": "uint256", + "name": "counted", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "reductionFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "refreshEpochExtraMinDuration", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "registryIndexPlus1", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_validators", + "type": "address[]" + } + ], + "name": "registryIndexesOf", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "remainingUnbanAllowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "removeAllValidatorBansExceptPermanent", + "outputs": [ + { + "internalType": "uint256", + "name": "removedCount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "remainingTemporary", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "removeValidatorBan", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "removeValidatorQuarantine", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + } + ], + "name": "requestInflationIfNeeded", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "_indexes", + "type": "uint256[]" + } + ], + "name": "resolveRegistryIndexes", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "revealingPhaseAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_randomSeed", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_slot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_txCreatedTimestamp", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_excludedActivator", + "type": "address" + } + ], + "name": "selectPendingActivator", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "selectableValidators", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "selectableValidatorsCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "_registryIndexes", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "_quarantineVersion", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_judicialSelectionVersion", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_verdictEpoch", + "type": "uint256" + } + ], + "name": "selectionBarredAtVersions", + "outputs": [ + { + "internalType": "uint256", + "name": "barredBits", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "judiciallyBarredBits", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + } + ], + "name": "selectionEconomicUnavailableBitmap", + "outputs": [ + { + "internalType": "uint256[7]", + "name": "bitmap", + "type": "uint256[7]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + } + ], + "name": "selectionEpochParameters", + "outputs": [ + { + "internalType": "uint256", + "name": "minimumStake", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxUtil", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + } + ], + "name": "selectionPoolSnapshot", + "outputs": [ + { + "internalType": "uint256[]", + "name": "indexes", + "type": "uint256[]" + }, + { + "internalType": "bytes32", + "name": "snapshotHash", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + } + ], + "name": "selectionPoolSnapshotAuthority", + "outputs": [ + { + "internalType": "uint256", + "name": "count", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "generation", + "type": "uint64" + }, + { + "internalType": "address", + "name": "pointer", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "runtimeCodeHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "snapshotHash", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_count", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "_generation", + "type": "uint64" + }, + { + "internalType": "address", + "name": "_pointer", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_runtimeCodeHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_snapshotHash", + "type": "bytes32" + } + ], + "name": "selectionPoolSnapshotFromAuthority", + "outputs": [ + { + "internalType": "uint256[]", + "name": "indexes", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "frozenUtilities", + "type": "uint256[]" + }, + { + "internalType": "uint256[7]", + "name": "liveUnavailableBits", + "type": "uint256[7]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_txCreatedTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "_sortedConsumedRegistryIndexes", + "type": "uint256[]" + } + ], + "name": "selectionPoolUnavailableCount", + "outputs": [ + { + "internalType": "uint256", + "name": "poolCount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "unavailableCount", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "seed", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "slot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "number", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "count", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "generation", + "type": "uint64" + }, + { + "internalType": "address", + "name": "pointer", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "runtimeCodeHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "snapshotHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "maxUtil", + "type": "uint256" + }, + { + "internalType": "uint256[7]", + "name": "temporaryUnavailableBits", + "type": "uint256[7]" + }, + { + "internalType": "uint256[]", + "name": "consumedRegistryIndexes", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "priorSlotPenalizedRegistryIndexes", + "type": "uint256[]" + } + ], + "internalType": "struct IGenLayerStaking.SnapshotSelectionRequest", + "name": "_request", + "type": "tuple" + } + ], + "name": "selectionPoolUnavailableCountFromSnapshotAuthority", + "outputs": [ + { + "internalType": "uint256", + "name": "poolCount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "unavailableCount", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "seed", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "slot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "number", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "count", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "generation", + "type": "uint64" + }, + { + "internalType": "address", + "name": "pointer", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "runtimeCodeHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "snapshotHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "maxUtil", + "type": "uint256" + }, + { + "internalType": "uint256[7]", + "name": "temporaryUnavailableBits", + "type": "uint256[7]" + }, + { + "internalType": "uint256[]", + "name": "consumedRegistryIndexes", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "priorSlotPenalizedRegistryIndexes", + "type": "uint256[]" + } + ], + "internalType": "struct IGenLayerStaking.SnapshotSelectionRequest", + "name": "_request", + "type": "tuple" + }, + { + "internalType": "uint256[]", + "name": "_registryIndexes", + "type": "uint256[]" + } + ], + "name": "selectionSnapshotPositionsFromAuthority", + "outputs": [ + { + "internalType": "uint256[]", + "name": "positions", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "foundBits", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_quarantineHistoryVersion", + "type": "uint256" + } + ], + "name": "selectionTemporaryUnavailableBitmap", + "outputs": [ + { + "internalType": "uint256[7]", + "name": "bitmap", + "type": "uint256[7]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_burnThreshold", + "type": "uint256" + } + ], + "name": "setBurnThreshold", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_daoFeeBps", + "type": "uint256" + } + ], + "name": "setDaoFeeBps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "_deepthought", + "type": "address" + } + ], + "name": "setDeepthought", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_delegatorMinStake", + "type": "uint256" + } + ], + "name": "setDelegatorMinimumStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epochExtraMinDuration", + "type": "uint256" + } + ], + "name": "setEpochExtraMinDurationOverride", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epochMinDuration", + "type": "uint256" + } + ], + "name": "setEpochMinDuration", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epochMinDurationThreshold", + "type": "uint256" + } + ], + "name": "setEpochMinDurationThreshold", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epochZeroMinDuration", + "type": "uint256" + } + ], + "name": "setEpochZeroMinDuration", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_finalizationPhase", + "type": "address" + } + ], + "name": "setFinalizationPhase", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_gen", + "type": "address" + } + ], + "name": "setGen", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_idlenessPhase", + "type": "address" + } + ], + "name": "setIdlenessPhase", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_incentivePercentage", + "type": "uint256" + } + ], + "name": "setIncentivePercentage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_inflationRequestThreshold", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_inflationTargetAhead", + "type": "uint256" + } + ], + "name": "setInflationThresholds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_l2GasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_l2GasLimit", + "type": "uint256" + } + ], + "name": "setL1InflationGasParams", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_max", + "type": "uint256" + } + ], + "name": "setMaxUnbansPerEpoch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_maxValidators", + "type": "uint256" + } + ], + "name": "setMaxValidators", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_bps", + "type": "uint256" + } + ], + "name": "setPrimingSelfStakeBps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_reductionFactor", + "type": "uint256" + } + ], + "name": "setReductionFactor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_revealingPhase", + "type": "address" + } + ], + "name": "setRevealingPhase", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_transactionFeesManager", + "type": "address" + } + ], + "name": "setTransactionFeesManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_delegatorUnbondingPeriod", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_validatorUnbondingPeriod", + "type": "uint256" + } + ], + "name": "setUnbondingPeriods", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_alpha", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_beta", + "type": "uint256" + } + ], + "name": "setValidatorWeightParams", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + }, + { + "internalType": "enum IGenLayerStaking.JudicialCapacityDisposition", + "name": "_disposition", + "type": "uint8" + } + ], + "name": "settleJudicialSuspension", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_delegator", + "type": "address" + }, + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "sharesOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_delegator", + "type": "address" + }, + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "stakeOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_accusedAtEpoch", + "type": "uint256" + } + ], + "name": "suspendJudicially", + "outputs": [ + { + "internalType": "enum IGenLayerStaking.JudicialCapacityDisposition", + "name": "disposition", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "transactionFeesManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "tribunalEligibleRegistryIndexes", + "outputs": [ + { + "internalType": "uint256[]", + "name": "indexes", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "seed", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "slot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "number", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "count", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "generation", + "type": "uint64" + }, + { + "internalType": "address", + "name": "pointer", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "runtimeCodeHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "snapshotHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "maxUtil", + "type": "uint256" + }, + { + "internalType": "uint256[7]", + "name": "temporaryUnavailableBits", + "type": "uint256[7]" + }, + { + "internalType": "uint256[]", + "name": "consumedRegistryIndexes", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "priorSlotPenalizedRegistryIndexes", + "type": "uint256[]" + } + ], + "internalType": "struct IGenLayerStaking.SnapshotSelectionRequest", + "name": "_request", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "_quarantineHistoryVersion", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_judicialSelectionVersion", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_creationEpoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_pageSize", + "type": "uint256" + } + ], + "name": "tribunalEligibleRegistryIndexesPageFromSnapshotAuthority", + "outputs": [ + { + "internalType": "uint256[]", + "name": "indexes", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unbanCapConfigured", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + } + ], + "name": "unbansInEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "validatorBanCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "validatorBanned", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "untilEpochBanned", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "permanentlyBanned", + "type": "bool" + } + ], + "internalType": "struct IGenLayerStaking.BannedValidators", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "validatorClaim", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "validatorDelegatorCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_index", + "type": "uint256" + } + ], + "name": "validatorDeposit", + "outputs": [ + { + "internalType": "uint256", + "name": "epoch_", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "input", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "output", + "type": "uint256" + }, + { + "internalType": "uint120", + "name": "outstanding", + "type": "uint120" + }, + { + "internalType": "uint64", + "name": "epoch", + "type": "uint64" + }, + { + "internalType": "uint56", + "name": "linkToNextCommit", + "type": "uint56" + }, + { + "internalType": "bool", + "name": "priced", + "type": "bool" + }, + { + "internalType": "bool", + "name": "fragmented", + "type": "bool" + } + ], + "internalType": "struct IGenLayerStaking.Commit", + "name": "commit_", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "validatorDeposit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + } + ], + "name": "validatorDepositByEpoch", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "input", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "output", + "type": "uint256" + }, + { + "internalType": "uint120", + "name": "outstanding", + "type": "uint120" + }, + { + "internalType": "uint64", + "name": "epoch", + "type": "uint64" + }, + { + "internalType": "uint56", + "name": "linkToNextCommit", + "type": "uint56" + }, + { + "internalType": "bool", + "name": "priced", + "type": "bool" + }, + { + "internalType": "bool", + "name": "fragmented", + "type": "bool" + } + ], + "internalType": "struct IGenLayerStaking.Commit", + "name": "commit_", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "validatorDepositLen", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "validatorExit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "_operatorPubKey", + "type": "uint256[2]" + }, + { + "internalType": "bytes", + "name": "_possessionProof", + "type": "bytes" + } + ], + "name": "validatorJoin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "validatorMinStake", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "validatorMinimumStakePublishedVersion", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "validatorMinimumStakeTransition", + "outputs": [ + { + "components": [ + { + "internalType": "enum IGenLayerStaking.MinimumStakeTransitionStatus", + "name": "status", + "type": "uint8" + }, + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "fromPublishedVersion", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "baseGeneration", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "candidateGeneration", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "capacityVersion", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "weightVersion", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision", + "type": "uint64" + }, + { + "internalType": "uint24", + "name": "worksetCount", + "type": "uint24" + }, + { + "internalType": "uint24", + "name": "cursor", + "type": "uint24" + }, + { + "internalType": "uint24", + "name": "grandfatheredOccupancy", + "type": "uint24" + }, + { + "internalType": "address", + "name": "worksetPointer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "targetEpoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "oldMinimum", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "proposedMinimum", + "type": "uint256" + }, + { + "internalType": "int256", + "name": "weightDelta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "vcountDelta", + "type": "int256" + }, + { + "internalType": "bytes32", + "name": "worksetRuntimeCodeHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "worksetHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "attemptHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "candidateAccountingFingerprint", + "type": "bytes32" + } + ], + "internalType": "struct IGenLayerStaking.MinimumStakeTransition", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "validatorPermanentlyBanned", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "validatorPrime", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_at", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + } + ], + "name": "validatorQuarantine", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "validatorQuarantineCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_seed", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_slot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_txCreatedTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_number", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "_weighted", + "type": "bool" + }, + { + "internalType": "address[]", + "name": "_consumed", + "type": "address[]" + } + ], + "name": "validatorSelection", + "outputs": [ + { + "internalType": "uint256", + "name": "leader_", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "validators_", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "penalized_", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_seed", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_slot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_txCreatedTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_number", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "_weighted", + "type": "bool" + }, + { + "internalType": "address[]", + "name": "_consumed", + "type": "address[]" + } + ], + "name": "validatorSelection", + "outputs": [ + { + "internalType": "uint256", + "name": "leader_", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "validators_", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "penalized_", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_seed", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_number", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "_candidateIndexes", + "type": "uint256[]" + } + ], + "name": "validatorSelectionFromExactIndexes", + "outputs": [ + { + "internalType": "uint256[]", + "name": "selectedIndexes", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "rand", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_seed", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_number", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_txCreatedTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "_consumedRegistryIndexes", + "type": "uint256[]" + } + ], + "name": "validatorSelectionFromList", + "outputs": [ + { + "internalType": "uint256[]", + "name": "selectedIndexes", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "rand_", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "seed", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "slot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "number", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "count", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "generation", + "type": "uint64" + }, + { + "internalType": "address", + "name": "pointer", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "runtimeCodeHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "snapshotHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "maxUtil", + "type": "uint256" + }, + { + "internalType": "uint256[7]", + "name": "temporaryUnavailableBits", + "type": "uint256[7]" + }, + { + "internalType": "uint256[]", + "name": "consumedRegistryIndexes", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "priorSlotPenalizedRegistryIndexes", + "type": "uint256[]" + } + ], + "internalType": "struct IGenLayerStaking.SnapshotSelectionRequest", + "name": "_request", + "type": "tuple" + } + ], + "name": "validatorSelectionFromSnapshotAuthority", + "outputs": [ + { + "internalType": "uint256", + "name": "leader", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "validators", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "penalized", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "validatorView", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "eBanned", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "ePrimed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vStake", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vShares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "dStake", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "dShares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vDeposit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vWithdrawal", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "live", + "type": "bool" + } + ], + "internalType": "struct IGenLayerStaking.ValidatorView", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "validatorViewPrePrimed", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "eBanned", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "ePrimed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vStake", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vShares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "dStake", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "dShares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vDeposit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vWithdrawal", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "live", + "type": "bool" + } + ], + "internalType": "struct IGenLayerStaking.ValidatorView", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "validatorViewPrimed", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "eBanned", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "ePrimed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vStake", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vShares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "dStake", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "dShares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vDeposit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vWithdrawal", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "live", + "type": "bool" + } + ], + "internalType": "struct IGenLayerStaking.ValidatorView", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_index", + "type": "uint256" + } + ], + "name": "validatorWithdrawal", + "outputs": [ + { + "internalType": "uint256", + "name": "epoch_", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "input", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "output", + "type": "uint256" + }, + { + "internalType": "uint120", + "name": "outstanding", + "type": "uint120" + }, + { + "internalType": "uint64", + "name": "epoch", + "type": "uint64" + }, + { + "internalType": "uint56", + "name": "linkToNextCommit", + "type": "uint56" + }, + { + "internalType": "bool", + "name": "priced", + "type": "bool" + }, + { + "internalType": "bool", + "name": "fragmented", + "type": "bool" + } + ], + "internalType": "struct IGenLayerStaking.Commit", + "name": "commit_", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + } + ], + "name": "validatorWithdrawalByEpoch", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "input", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "output", + "type": "uint256" + }, + { + "internalType": "uint120", + "name": "outstanding", + "type": "uint120" + }, + { + "internalType": "uint64", + "name": "epoch", + "type": "uint64" + }, + { + "internalType": "uint56", + "name": "linkToNextCommit", + "type": "uint56" + }, + { + "internalType": "bool", + "name": "priced", + "type": "bool" + }, + { + "internalType": "bool", + "name": "fragmented", + "type": "bool" + } + ], + "internalType": "struct IGenLayerStaking.Commit", + "name": "commit_", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "validatorWithdrawalLen", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "validatorsJoined", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "validatorsJoinedCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } ] diff --git a/genlayer_py/staking/abi/validator_wallet_abi.json b/genlayer_py/staking/abi/validator_wallet_abi.json index cfd125a..c7aa641 100644 --- a/genlayer_py/staking/abi/validator_wallet_abi.json +++ b/genlayer_py/staking/abi/validator_wallet_abi.json @@ -1,1002 +1,1391 @@ [ - { - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - }, - { - "internalType": "address", - "name": "_staking", - "type": "address" - }, - { - "internalType": "address", - "name": "_consensus", - "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": [], - "name": "InvalidInitialization", - "type": "error" - }, - { - "inputs": [], - "name": "NotInitializing", - "type": "error" - }, - { - "inputs": [], - "name": "NotOperator", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "OwnableInvalidOwner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "OwnableUnauthorizedAccount", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrancyGuardReentrantCall", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "version", - "type": "uint64" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferStarted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "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" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "ValidatorIdentitySet", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "inputs": [], - "name": "DEFAULT_ADMIN_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "_vrfProof", - "type": "bytes" - } - ], - "name": "activateTransaction", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_tribunalIndex", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "_commitHash", - "type": "bytes32" - } - ], - "name": "commitTribunalAppealVote", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "_commitHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_validatorIndex", - "type": "uint256" - } - ], - "name": "commitVote", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "consensus", - "outputs": [ - { - "internalType": "contract IConsensusMain", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "consensusWithFees", - "outputs": [ - { - "internalType": "contract IConsensusMainWithFees", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getIdentity", - "outputs": [ - { - "components": [ - { - "internalType": "string", - "name": "moniker", - "type": "string" - }, - { - "internalType": "string", - "name": "logoUri", - "type": "string" - }, - { - "internalType": "string", - "name": "website", - "type": "string" - }, - { - "internalType": "string", - "name": "description", - "type": "string" - }, - { - "internalType": "string", - "name": "email", - "type": "string" - }, - { - "internalType": "string", - "name": "twitter", - "type": "string" - }, - { - "internalType": "string", - "name": "telegram", - "type": "string" - }, - { - "internalType": "string", - "name": "github", - "type": "string" - }, - { - "internalType": "bytes", - "name": "extraCid", - "type": "bytes" - } - ], - "internalType": "struct ValidatorIdentity", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getOperator", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "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": [], - "name": "identity", - "outputs": [ - { - "internalType": "string", - "name": "moniker", - "type": "string" - }, - { - "internalType": "string", - "name": "logoUri", - "type": "string" - }, - { - "internalType": "string", - "name": "website", - "type": "string" - }, - { - "internalType": "string", - "name": "description", - "type": "string" - }, - { - "internalType": "string", - "name": "email", - "type": "string" - }, - { - "internalType": "string", - "name": "twitter", - "type": "string" - }, - { - "internalType": "string", - "name": "telegram", - "type": "string" - }, - { - "internalType": "string", - "name": "github", - "type": "string" - }, - { - "internalType": "bytes", - "name": "extraCid", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "txId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "saltAsAValidator", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "txExecutionHash", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "messagesAndOtherFieldsHash", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "otherExecutionFieldsHash", - "type": "bytes32" - }, - { - "internalType": "enum ITransactions.VoteType", - "name": "resultValue", - "type": "uint8" - }, - { - "components": [ - { - "internalType": "enum IMessages.MessageType", - "name": "messageType", - "type": "uint8" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "bool", - "name": "onAcceptance", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "saltNonce", - "type": "uint256" - } - ], - "internalType": "struct IMessages.SubmittedMessage[]", - "name": "messages", - "type": "tuple[]" - } - ], - "internalType": "struct IConsensusMain.LeaderRevealVoteParams", - "name": "_leaderRevealVoteParams", - "type": "tuple" - } - ], - "name": "leaderRevealVote", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "operator", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pendingOwner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "_txExecutionHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_processingBlock", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_eqBlocksOutputs", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "_vrfProof", - "type": "bytes" - } - ], - "name": "proposeReceipt", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "_txExecutionHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_processingBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_storageFeeUsed", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_eqBlocksOutputs", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "_vrfProof", - "type": "bytes" - } - ], - "name": "proposeReceiptWithFees", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "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": "_txId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_tribunalIndex", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "_voteHash", - "type": "bytes32" - }, - { - "internalType": "enum ITransactions.VoteType", - "name": "_voteType", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "_otherExecutionFieldsHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_nonce", - "type": "uint256" - } - ], - "name": "revealTribunalAppealVote", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "_voteHash", - "type": "bytes32" - }, - { - "internalType": "enum ITransactions.VoteType", - "name": "_voteType", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "_otherExecutionFieldsHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_nonce", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_validatorIndex", - "type": "uint256" - } - ], - "name": "revealVote", - "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": "address", - "name": "_consensus", - "type": "address" - }, - { - "internalType": "address", - "name": "_consensusWithFees", - "type": "address" - }, - { - "internalType": "address", - "name": "_staking", - "type": "address" - } - ], - "name": "setExternalAddresses", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "moniker", - "type": "string" - }, - { - "internalType": "string", - "name": "logoUri", - "type": "string" - }, - { - "internalType": "string", - "name": "website", - "type": "string" - }, - { - "internalType": "string", - "name": "description", - "type": "string" - }, - { - "internalType": "string", - "name": "email", - "type": "string" - }, - { - "internalType": "string", - "name": "twitter", - "type": "string" - }, - { - "internalType": "string", - "name": "telegram", - "type": "string" - }, - { - "internalType": "string", - "name": "github", - "type": "string" - }, - { - "internalType": "bytes", - "name": "extraCid", - "type": "bytes" - } - ], - "name": "setIdentity", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_operator", - "type": "address" - } - ], - "name": "setOperator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "staking", - "outputs": [ - { - "internalType": "contract IGenLayerStaking", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "validatorClaim", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "validatorDeposit", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_shares", - "type": "uint256" - } - ], - "name": "validatorExit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } + { + "inputs": [], + "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": [], + "name": "InvalidAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPossessionProof", + "type": "error" + }, + { + "inputs": [], + "name": "NoPendingOperator", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [], + "name": "NotOperator", + "type": "error" + }, + { + "inputs": [], + "name": "OperatorTransferNotReady", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "PubKeyIsZero", + "type": "error" + }, + { + "inputs": [], + "name": "PubKeyNotOnCurve", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrancyGuardReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "TransferFailed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "newOperator", + "type": "address" + } + ], + "name": "OperatorSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "by", + "type": "address" + } + ], + "name": "OperatorTransferCancelled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OperatorTransferCompleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "transferableAt", + "type": "uint256" + } + ], + "name": "OperatorTransferStarted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "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" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ValidatorClaimProcessed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ValidatorDepositMade", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "ValidatorExitInitiated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "ValidatorIdentitySet", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "OPERATOR_TRANSFER_DELAY", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "_vrfProof", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "_expectedAttemptId", + "type": "bytes32" + } + ], + "name": "activateTransaction", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "cancelOperatorTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_tribunalIndex", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "_commitHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_activeIndex", + "type": "uint256" + } + ], + "name": "commitTribunalAppealVote", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_commitHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_validatorIndex", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "_expectedAttemptId", + "type": "bytes32" + } + ], + "name": "commitVote", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "completeOperatorTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "consensus", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "consensusWithFees", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getIdentity", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "moniker", + "type": "string" + }, + { + "internalType": "string", + "name": "logoUri", + "type": "string" + }, + { + "internalType": "string", + "name": "website", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + }, + { + "internalType": "string", + "name": "email", + "type": "string" + }, + { + "internalType": "string", + "name": "twitter", + "type": "string" + }, + { + "internalType": "string", + "name": "telegram", + "type": "string" + }, + { + "internalType": "string", + "name": "github", + "type": "string" + }, + { + "internalType": "bytes", + "name": "extraCid", + "type": "bytes" + } + ], + "internalType": "struct IValidatorWallet.ValidatorIdentity", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getOperator", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getOperatorPubKey", + "outputs": [ + { + "internalType": "uint256[2]", + "name": "", + "type": "uint256[2]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPendingOperator", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "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": [], + "name": "identity", + "outputs": [ + { + "internalType": "string", + "name": "moniker", + "type": "string" + }, + { + "internalType": "string", + "name": "logoUri", + "type": "string" + }, + { + "internalType": "string", + "name": "website", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + }, + { + "internalType": "string", + "name": "email", + "type": "string" + }, + { + "internalType": "string", + "name": "twitter", + "type": "string" + }, + { + "internalType": "string", + "name": "telegram", + "type": "string" + }, + { + "internalType": "string", + "name": "github", + "type": "string" + }, + { + "internalType": "bytes", + "name": "extraCid", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_factory", + "type": "address" + }, + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_staking", + "type": "address" + }, + { + "internalType": "address", + "name": "_consensus", + "type": "address" + }, + { + "internalType": "uint256[2]", + "name": "_operatorPubKey", + "type": "uint256[2]" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "_newOperatorPubKey", + "type": "uint256[2]" + }, + { + "internalType": "bytes", + "name": "_possessionProof", + "type": "bytes" + } + ], + "name": "initiateOperatorTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "expectedAttemptId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "saltAsAValidator", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "txExecutionHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "messagesAndOtherFieldsHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "otherExecutionFieldsHash", + "type": "bytes32" + }, + { + "internalType": "enum ITransactions.VoteType", + "name": "resultValue", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "enum IMessages.MessageType", + "name": "messageType", + "type": "uint8" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "onAcceptance", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "saltNonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "feeParams", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "declaredBudget", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "allocationSubtree", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "callKey", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "useBalance", + "type": "bool" + } + ], + "internalType": "struct IMessages.SubmittedMessage[]", + "name": "messages", + "type": "tuple[]" + } + ], + "internalType": "struct IConsensusMain.LeaderRevealVoteParams", + "name": "_params", + "type": "tuple" + } + ], + "name": "leaderRevealVote", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "operator", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "operatorPubKey", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "operatorTransferInitiated", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOperator", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "pendingOperatorPubKey", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_txExecutionHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_processingBlock", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_eqBlocksOutputs", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "_vrfProof", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "_expectedAttemptId", + "type": "bytes32" + } + ], + "name": "proposeReceipt", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_txExecutionHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_processingBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_storageFeeUsed", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_eqBlocksOutputs", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "_vrfProof", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "_expectedAttemptId", + "type": "bytes32" + } + ], + "name": "proposeReceiptWithFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_txExecutionHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_processingBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_storageFeeUsed", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_eqBlocksOutputs", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "_vrfProof", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "_reportedMessageFeesTotal", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "_expectedAttemptId", + "type": "bytes32" + } + ], + "name": "proposeReceiptWithMessages", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "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": "_txId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_tribunalIndex", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "_voteHash", + "type": "bytes32" + }, + { + "internalType": "enum ITransactions.VoteType", + "name": "_voteType", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "_otherExecutionFieldsHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_activeIndex", + "type": "uint256" + } + ], + "name": "revealTribunalAppealVote", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_voteHash", + "type": "bytes32" + }, + { + "internalType": "enum ITransactions.VoteType", + "name": "_voteType", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "_otherExecutionFieldsHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_validatorIndex", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "_expectedAttemptId", + "type": "bytes32" + } + ], + "name": "revealVote", + "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": "address", + "name": "_consensus", + "type": "address" + }, + { + "internalType": "address", + "name": "_consensusWithFees", + "type": "address" + }, + { + "internalType": "address", + "name": "_staking", + "type": "address" + } + ], + "name": "setExternalAddresses", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "moniker", + "type": "string" + }, + { + "internalType": "string", + "name": "logoUri", + "type": "string" + }, + { + "internalType": "string", + "name": "website", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + }, + { + "internalType": "string", + "name": "email", + "type": "string" + }, + { + "internalType": "string", + "name": "twitter", + "type": "string" + }, + { + "internalType": "string", + "name": "telegram", + "type": "string" + }, + { + "internalType": "string", + "name": "github", + "type": "string" + }, + { + "internalType": "bytes", + "name": "extraCid", + "type": "bytes" + } + ], + "name": "setIdentity", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "_operatorPubKey", + "type": "uint256[2]" + }, + { + "internalType": "bytes", + "name": "_possessionProof", + "type": "bytes" + } + ], + "name": "setOperatorPubKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "staking", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "validatorClaim", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "validatorDeposit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_shares", + "type": "uint256" + } + ], + "name": "validatorExit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } ] diff --git a/genlayer_py/staking/actions.py b/genlayer_py/staking/actions.py index 065b465..09f383e 100644 --- a/genlayer_py/staking/actions.py +++ b/genlayer_py/staking/actions.py @@ -15,8 +15,14 @@ from eth_typing import Address, ChecksumAddress from hexbytes import HexBytes +from genlayer_py.consensus.abi import ADDRESS_MANAGER_ABI from genlayer_py.exceptions import GenLayerError from genlayer_py.staking.abi import STAKING_ABI, VALIDATOR_WALLET_ABI +from genlayer_py.staking.operator_registration import ( + OperatorRegistrationContext, + OperatorRegistrationProof, + verify_operator_registration, +) if TYPE_CHECKING: from genlayer_py.client import GenLayerClient @@ -24,6 +30,14 @@ AddressLike = Union[Address, ChecksumAddress, str] +ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" + +# The joined validator registry is only readable in slices: committee capacity +# is 1,543 and an address[] that long overruns the return-size limit. 64 is the +# size the paged reads are written around, and the one genlayer-node uses for +# the same walk. +VALIDATORS_JOINED_PAGE_SIZE = 64 + def _require_staking(self: "GenLayerClient") -> ChecksumAddress: if self.chain.staking_contract is None: @@ -43,9 +57,7 @@ def _wallet(self: "GenLayerClient", validator: AddressLike): ) -def _sender( - self: "GenLayerClient", account: Optional[LocalAccount] -) -> LocalAccount: +def _sender(self: "GenLayerClient", account: Optional[LocalAccount]) -> LocalAccount: acct = account or self.local_account if acct is None: raise GenLayerError("No account provided and client has no local_account") @@ -92,11 +104,38 @@ def epoch(self: "GenLayerClient") -> int: def active_validators(self: "GenLayerClient") -> List[ChecksumAddress]: - return _staking(self).functions.activeValidators().call() + """Return validators that are currently eligible for protocol duties.""" + return _staking(self).functions.selectableValidators().call() def active_validators_count(self: "GenLayerClient") -> int: - return _staking(self).functions.activeValidatorsCount().call() + """Return the number of validators currently eligible for duties.""" + return _staking(self).functions.selectableValidatorsCount().call() + + +def joined_validators(self: "GenLayerClient") -> List[ChecksumAddress]: + """Return every validator wallet in the append-only joined registry.""" + # The joined registry can contain 1,543 entries, so read it in slices. The + # count is read first so a registry that grows underneath the walk cannot + # spin forever, and an empty page lets a shrinking walk stop safely. + staking = _staking(self) + total = staking.functions.validatorsJoinedCount().call() + + validators: List[ChecksumAddress] = [] + for start in range(0, total, VALIDATORS_JOINED_PAGE_SIZE): + page = staking.functions.getValidatorsJoined( + start, VALIDATORS_JOINED_PAGE_SIZE + ).call() + if not page: + break + validators.extend(page) + + return [v for v in validators if v != ZERO_ADDRESS] + + +def joined_validators_count(self: "GenLayerClient") -> int: + """Return the size of the append-only joined validator registry.""" + return _staking(self).functions.validatorsJoinedCount().call() def is_validator(self: "GenLayerClient", address: AddressLike) -> bool: @@ -147,25 +186,62 @@ def delegator_min_stake(self: "GenLayerClient") -> int: # ─── write methods ──────────────────────────────────────────────────── +def get_validator_join_context( + self: "GenLayerClient", + account: Optional[LocalAccount] = None, +) -> OperatorRegistrationContext: + """Return the factory-bound context required for a validator join proof.""" + sender = _sender(self, account) + address_manager_address = _staking(self).functions.addressManager().call() + address_manager = self.w3.eth.contract( + address=self.w3.to_checksum_address(address_manager_address), + abi=ADDRESS_MANAGER_ABI, + ) + factory = address_manager.functions.getAddressNonZero( + "ValidatorWalletFactory" + ).call() + return OperatorRegistrationContext( + registrar=self.w3.to_checksum_address(factory), + owner=self.w3.to_checksum_address(sender.address), + chain_id=self.w3.eth.chain_id, + ) + + def validator_join( self: "GenLayerClient", amount: int, - operator: Optional[AddressLike] = None, + registration: Optional[OperatorRegistrationProof] = None, account: Optional[LocalAccount] = None, + operator: Optional[AddressLike] = None, ) -> HexBytes: - """Joins as a validator with `amount` GEN stake. Deploys a new - ValidatorWallet. Returns the tx hash — call get_validator_info on - the resulting wallet address to discover it (or parse the receipt - for the ValidatorJoin event).""" + """Join with a proof-bound operator key and deploy a ValidatorWallet. + + Build ``registration`` with :func:`get_validator_join_context` and + ``create_operator_registration``. The legacy address-only overloads do not + exist on the train. + """ + if operator is not None or not isinstance(registration, OperatorRegistrationProof): + raise GenLayerError( + "validator_join now requires an OperatorRegistrationProof; call " + "get_validator_join_context(), create_operator_registration(), then " + "pass the resulting registration. An operator address alone is not " + "accepted by the train contract." + ) + sender = _sender(self, account) + context = get_validator_join_context(self, account) + if not verify_operator_registration(registration, context): + raise GenLayerError( + "Operator registration proof does not match the validator wallet " + "factory, owner, chain, or public key. Build a fresh proof from " + "get_validator_join_context()." + ) + contract = _staking(self) - # Staking.validatorJoin has two overloads — () and (address) — so - # web3.py needs the full signature, not the name alone. - if operator is not None: - op = self.w3.to_checksum_address(operator) - data = contract.encode_abi("validatorJoin(address)", args=[op]) - else: - data = contract.encode_abi("validatorJoin()", args=[]) + data = contract.encode_abi( + "validatorJoin", + args=[list(registration.operator_pub_key), registration.possession_proof], + ) tx = _build(self, sender, _require_staking(self), data, value=amount) return _send(self, sender, tx) @@ -181,7 +257,9 @@ def validator_deposit( sender = _sender(self, account) wallet = _wallet(self, validator) data = wallet.encode_abi("validatorDeposit", args=[]) - tx = _build(self, sender, self.w3.to_checksum_address(validator), data, value=amount) + tx = _build( + self, sender, self.w3.to_checksum_address(validator), data, value=amount + ) return _send(self, sender, tx) @@ -236,17 +314,98 @@ def set_operator( operator: AddressLike, account: Optional[LocalAccount] = None, ) -> HexBytes: - """Rotates the operator for an existing ValidatorWallet. Only the - wallet owner (the EOA that called validator_join) may do this.""" + """Explain how to migrate from the removed address-only rotation call.""" + raise GenLayerError( + "set_operator(address) was removed from the train contract and no " + "transaction was sent. Build a proof with " + "get_operator_transfer_context(), call initiate_operator_transfer(), " + "then complete_operator_transfer() after the transfer delay." + ) + + +def get_operator_transfer_context( + self: "GenLayerClient", validator: AddressLike +) -> OperatorRegistrationContext: + """Context for a rotation proof. + + Rotation is verified by the wallet rather than the factory, so the + registrar is the wallet's own address. The owner is read from the wallet + instead of assumed to be the caller: the proof is bound to whatever + owner() returns, and a mismatch is easier to diagnose here than as an + onlyOwner revert.""" + wallet = _wallet(self, validator) + return OperatorRegistrationContext( + registrar=self.w3.to_checksum_address(validator), + owner=self.w3.to_checksum_address(wallet.functions.owner().call()), + chain_id=self.w3.eth.chain_id, + ) + + +def initiate_operator_transfer( + self: "GenLayerClient", + validator: AddressLike, + registration: OperatorRegistrationProof, + account: Optional[LocalAccount] = None, +) -> HexBytes: + """Starts the two-step operator rotation. Owner only. + + `registration` must be built against get_operator_transfer_context — a + join proof is bound to the factory and will not verify here.""" + context = get_operator_transfer_context(self, validator) + if not verify_operator_registration(registration, context): + raise GenLayerError( + "Operator registration proof does not match the wallet, owner, chain, " + "or public key. Rotation proofs must use the validator wallet as " + "their registrar." + ) + sender = _sender(self, account) wallet = _wallet(self, validator) data = wallet.encode_abi( - "setOperator", args=[self.w3.to_checksum_address(operator)] + "initiateOperatorTransfer", + args=[list(registration.operator_pub_key), registration.possession_proof], ) tx = _build(self, sender, self.w3.to_checksum_address(validator), data) return _send(self, sender, tx) +def complete_operator_transfer( + self: "GenLayerClient", + validator: AddressLike, + account: Optional[LocalAccount] = None, +) -> HexBytes: + """Finalises a pending rotation. Callable by the wallet owner or the + pending operator, once the factory's operatorTransferDelay has elapsed.""" + sender = _sender(self, account) + wallet = _wallet(self, validator) + data = wallet.encode_abi("completeOperatorTransfer", args=[]) + tx = _build(self, sender, self.w3.to_checksum_address(validator), data) + return _send(self, sender, tx) + + +def cancel_operator_transfer( + self: "GenLayerClient", + validator: AddressLike, + account: Optional[LocalAccount] = None, +) -> HexBytes: + """Abandons a pending rotation, leaving the current operator in place.""" + sender = _sender(self, account) + wallet = _wallet(self, validator) + data = wallet.encode_abi("cancelOperatorTransfer", args=[]) + tx = _build(self, sender, self.w3.to_checksum_address(validator), data) + return _send(self, sender, tx) + + +def get_pending_operator(self: "GenLayerClient", validator: AddressLike) -> dict: + """Pending operator and when its transfer was initiated (0 when none).""" + wallet = _wallet(self, validator) + operator, initiated_at = wallet.functions.getPendingOperator().call() + return { + "operator": self.w3.to_checksum_address(operator), + "initiated_at": int(initiated_at), + } + + def set_identity( self: "GenLayerClient", validator: AddressLike, diff --git a/genlayer_py/staking/operator_registration.py b/genlayer_py/staking/operator_registration.py new file mode 100644 index 0000000..b182ad5 --- /dev/null +++ b/genlayer_py/staking/operator_registration.py @@ -0,0 +1,135 @@ +"""Proof of possession for operator keys. + +Consensus requires an operator to prove control of its key before that key is +bound to a validator wallet. The proof is an EIP-191 signature, by the operator +key, over a domain-separated hash of (chainId, registrar, owner, pubKey). + +`registrar` is whichever contract verifies the proof, and it differs by flow: +the ValidatorWalletFactory for a validator join, the wallet itself for an +operator rotation (ValidatorWalletBlueprint.initiateOperatorTransfer calls +PubKeyUtils.validateWithPossession(pubKey, address(this), owner(), proof)). +Passing the wrong one produces a proof that simply fails to verify. + +The encoding mirrors genlayer-js's createOperatorRegistration exactly — the +shared vector in tests/unit/test_operator_registration.py pins the two +implementations together. +""" + +from __future__ import annotations + +from dataclasses import dataclass +from typing import Tuple + +from eth_abi.abi import encode as abi_encode +from eth_account import Account +from eth_account.messages import encode_defunct +from eth_typing import ChecksumAddress +from eth_utils.address import to_checksum_address +from eth_utils.crypto import keccak + +OPERATOR_REGISTRATION_DOMAIN = keccak( + text="GenLayer/operatorPubKey/proof-of-possession/v1" +) + +OperatorPublicKey = Tuple[int, int] + + +@dataclass(frozen=True) +class OperatorRegistrationContext: + """Who verifies the proof, on whose behalf, and on which chain.""" + + registrar: ChecksumAddress + owner: ChecksumAddress + chain_id: int + + +@dataclass(frozen=True) +class OperatorRegistrationProof: + operator: ChecksumAddress + operator_pub_key: OperatorPublicKey + possession_proof: bytes + + +def operator_public_key_from_private_key(private_key: str) -> OperatorPublicKey: + """Splits the uncompressed secp256k1 public key into the contract's + uint256[2] tuple.""" + account = Account.from_key(private_key) + public_key = account._key_obj.public_key.to_bytes() + return ( + int.from_bytes(public_key[0:32], "big"), + int.from_bytes(public_key[32:64], "big"), + ) + + +def operator_address_from_public_key(pub_key: OperatorPublicKey) -> ChecksumAddress: + raw = pub_key[0].to_bytes(32, "big") + pub_key[1].to_bytes(32, "big") + return to_checksum_address(keccak(raw)[-20:]) + + +def operator_possession_message( + pub_key: OperatorPublicKey, context: OperatorRegistrationContext +) -> bytes: + return keccak( + abi_encode( + ["bytes32", "uint256", "address", "address", "uint256", "uint256"], + [ + OPERATOR_REGISTRATION_DOMAIN, + context.chain_id, + context.registrar, + context.owner, + pub_key[0], + pub_key[1], + ], + ) + ) + + +def create_operator_registration( + private_key: str, context: OperatorRegistrationContext +) -> OperatorRegistrationProof: + """Builds the proof package the proof-bearing calls consume. + + The private key is used only to sign and is never retained in the result. + """ + account = Account.from_key(private_key) + pub_key = operator_public_key_from_private_key(private_key) + operator = operator_address_from_public_key(pub_key) + + if operator != to_checksum_address(account.address): + raise ValueError( + "Operator private key and public key derive different identities." + ) + + signed = Account.sign_message( + encode_defunct(operator_possession_message(pub_key, context)), + private_key=private_key, + ) + + return OperatorRegistrationProof( + operator=operator, + operator_pub_key=pub_key, + possession_proof=bytes(signed.signature), + ) + + +def verify_operator_registration( + registration: OperatorRegistrationProof, + context: OperatorRegistrationContext, +) -> bool: + """Checks key identity and the exact registrar/owner/chain binding.""" + if operator_address_from_public_key(registration.operator_pub_key) != to_checksum_address( + registration.operator + ): + return False + + message = encode_defunct( + operator_possession_message(registration.operator_pub_key, context) + ) + try: + recovered = Account.recover_message( + message, signature=registration.possession_proof + ) + except Exception: + return False + + return to_checksum_address(recovered) == to_checksum_address(registration.operator) diff --git a/genlayer_py/transactions/__init__.py b/genlayer_py/transactions/__init__.py index 3674413..4f215f6 100644 --- a/genlayer_py/transactions/__init__.py +++ b/genlayer_py/transactions/__init__.py @@ -2,32 +2,46 @@ CALL_KEY_DEPLOY, CALL_KEY_UNNAMED, CALL_KEY_WILDCARD, + DEPLOY_CALL_KEY, MESSAGE_ALLOCATION_ROOT_PARENT_INDEX, DEFAULT_FEES_DISTRIBUTION, MessageType, build_estimated_fees_distribution, calculate_local_round_fees, create_fees_distribution, + create_top_up_fees_distribution, derive_external_message_call_key, + deploy_call_key, derive_internal_message_call_key, encode_external_message_fee_params, encode_internal_message_fee_params, extract_studio_fee_policy, ) + +def is_successful(transaction): + from .actions import is_successful as _is_successful + + return _is_successful(transaction) + + __all__ = [ "CALL_KEY_DEPLOY", "CALL_KEY_UNNAMED", "CALL_KEY_WILDCARD", + "DEPLOY_CALL_KEY", "MESSAGE_ALLOCATION_ROOT_PARENT_INDEX", "DEFAULT_FEES_DISTRIBUTION", "MessageType", "build_estimated_fees_distribution", "calculate_local_round_fees", "create_fees_distribution", + "create_top_up_fees_distribution", "derive_external_message_call_key", + "deploy_call_key", "derive_internal_message_call_key", "encode_external_message_fee_params", "encode_internal_message_fee_params", "extract_studio_fee_policy", + "is_successful", ] diff --git a/genlayer_py/transactions/actions.py b/genlayer_py/transactions/actions.py index 3da21f1..4d872f5 100644 --- a/genlayer_py/transactions/actions.py +++ b/genlayer_py/transactions/actions.py @@ -2,24 +2,38 @@ from genlayer_py.logging import logger import json -from typing import Any, Dict, List +from typing import Any, Dict, List, Literal, Optional from web3 import Web3 from web3.types import _Hash32 -from eth_typing import HexStr +from eth_typing import Address, HexStr from web3.logs import DISCARD from genlayer_py.config import transaction_config from genlayer_py.types import ( - TransactionStatus, - TRANSACTION_STATUS_NAME_TO_NUMBER, - TRANSACTION_STATUS_NUMBER_TO_NAME, - is_decided_state, + ExecutionResult, + EXECUTION_RESULT_NUMBER_TO_NAME, +) +from genlayer_py.types.transactions import ( + PROTOCOL_TRANSACTION_STATUS_NAME_TO_NUMBER, + PROTOCOL_TRANSACTION_STATUS_NUMBER_TO_NAME, + RESOLUTION_ACTION_NUMBER_TO_NAME, + RESOLUTION_SOURCE_NUMBER_TO_NAME, + ProtocolTransactionLifecycle, + ProtocolTransactionStatus, + transaction_lifecycle_from_protocol_status, + transaction_outcome_from_protocol_result, +) +from genlayer_py.consensus.abi import ( + ADDRESS_MANAGER_ABI, + CONSENSUS_DATA_BIG_ROUNDS_ABI, + ROUNDS_STORAGE_READ_ABI, + TRANSACTION_MANAGER_READ_ABI, ) from genlayer_py.exceptions import GenLayerError from typing import TYPE_CHECKING from genlayer_py.types import GenLayerTransaction, GenLayerRawTransaction import time -from genlayer_py.chains import localnet +from genlayer_py.chains.utils import is_studio_chain from genlayer_py.utils.jsonifier import ( calldata_to_user_friendly_json, result_to_user_friendly_json, @@ -66,75 +80,661 @@ from genlayer_py.client import GenLayerClient -def wait_for_transaction_receipt( +TRANSACTION_ARRAY_PAGE_SIZE = 64 + + +def _normalize_execution_result_name(value: Any) -> Optional[ExecutionResult]: + if isinstance(value, ExecutionResult): + return value + if isinstance(value, str) and value in ExecutionResult._value2member_map_: + return ExecutionResult(value) + if value is None: + return None + return EXECUTION_RESULT_NUMBER_TO_NAME.get(str(value)) + + +def is_successful(transaction: GenLayerTransaction) -> bool: + lifecycle = transaction.get("lifecycle") + if not isinstance(lifecycle, dict): + return False + lifecycle_state = lifecycle.get("state") + successful_lifecycle = ( + lifecycle_state == "finalized" + and lifecycle.get("outcome") in (None, "accepted") + ) or (lifecycle_state == "decided" and lifecycle.get("outcome") == "accepted") + execution_result_name = _normalize_execution_result_name( + transaction.get( + "tx_execution_result_name", + transaction.get("tx_execution_result"), + ) + ) + + if execution_result_name is None: + consensus_data = transaction.get("consensus_data") + if isinstance(consensus_data, dict): + leader_receipt = consensus_data.get("leader_receipt") + if isinstance(leader_receipt, list): + leader_receipt = leader_receipt[0] if leader_receipt else None + if ( + isinstance(leader_receipt, dict) + and leader_receipt.get("execution_result") == "SUCCESS" + ): + execution_result_name = ExecutionResult.FINISHED_WITH_RETURN + + return ( + successful_lifecycle + and execution_result_name == ExecutionResult.FINISHED_WITH_RETURN + ) + + +def _wait_for_transaction( self: GenLayerClient, transaction_hash: _Hash32, - status: TransactionStatus = TransactionStatus.ACCEPTED, + wait_until: Literal["decided", "finalized"], interval: int = transaction_config.wait_interval, retries: int = transaction_config.retries, full_transaction: bool = False, ) -> GenLayerTransaction: - attempts = 0 + transaction = None + last_state = None while attempts < retries: transaction = self.get_transaction(transaction_hash=transaction_hash) if transaction is None: raise GenLayerError(f"Transaction {transaction_hash} not found") - transaction_status = str(transaction["status"]) - last_status = TRANSACTION_STATUS_NUMBER_TO_NAME[transaction_status] - finalized_status = TRANSACTION_STATUS_NAME_TO_NUMBER[ - TransactionStatus.FINALIZED - ] - requested_status = TRANSACTION_STATUS_NAME_TO_NUMBER[status] - - if transaction_status == requested_status or ( - status == TransactionStatus.ACCEPTED - and is_decided_state(transaction_status) + lifecycle = transaction.get("lifecycle") + if not isinstance(lifecycle, dict) or not isinstance( + lifecycle.get("state"), str ): + raise GenLayerError( + f"Transaction {transaction_hash} has no valid lifecycle" + ) + last_state = lifecycle["state"] + reached_target = ( + last_state in ("decided", "finalized", "canceled") + if wait_until == "decided" + else last_state == "finalized" + ) + + if wait_until == "finalized" and last_state == "canceled": + raise GenLayerError( + f"Transaction {transaction_hash} was canceled before finalization" + ) + + if reached_target: if not full_transaction: return _simplify_transaction_receipt(transaction) return transaction time.sleep(interval / 1000) attempts += 1 raise GenLayerError( - f"Transaction {transaction_hash} did not reach desired status '{status.value}' after {retries} attempts " + f"Transaction {transaction_hash} did not reach '{wait_until}' after {retries} attempts " f"(polling every {interval}ms for a total of {retries * interval / 1000:.1f}s). " - f"Last observed status: '{last_status.value}'. " + f"Last observed lifecycle state: '{last_state or ''}'. " f"This may indicate the transaction is still processing, or the network is experiencing delays. " f"Consider increasing 'retries' or 'interval' parameters.\n" f"Transaction object simplified: {json.dumps(_simplify_transaction_receipt(transaction), indent=2, default=str)}" ) +def wait_for_decision( + self: GenLayerClient, + transaction_hash: _Hash32, + interval: int = transaction_config.wait_interval, + retries: int = transaction_config.retries, + full_transaction: bool = False, +) -> GenLayerTransaction: + """Poll until the stored transaction state is decided or terminal.""" + + return _wait_for_transaction( + self, + transaction_hash, + "decided", + interval, + retries, + full_transaction, + ) + + +def wait_for_finalization( + self: GenLayerClient, + transaction_hash: _Hash32, + interval: int = transaction_config.wait_interval, + retries: int = transaction_config.retries, + full_transaction: bool = False, +) -> GenLayerTransaction: + """Poll until the stored transaction state is finalized.""" + + return _wait_for_transaction( + self, + transaction_hash, + "finalized", + interval, + retries, + full_transaction, + ) + + +def wait_for_transaction_receipt( + self: GenLayerClient, + transaction_hash: _Hash32, + wait_until: Literal["decided", "finalized"] = "decided", + interval: int = transaction_config.wait_interval, + retries: int = transaction_config.retries, + full_transaction: bool = False, +) -> GenLayerTransaction: + """Poll for a stored decision (default) or stored finalization.""" + + if wait_until == "decided": + return wait_for_decision( + self, transaction_hash, interval, retries, full_transaction + ) + if wait_until == "finalized": + return wait_for_finalization( + self, transaction_hash, interval, retries, full_transaction + ) + raise ValueError("wait_until must be 'decided' or 'finalized'.") + + +def _call_at_block(contract_function, block_number: int): + return contract_function.call(block_identifier=block_number) + + +def _address_manager( + self: GenLayerClient, + consensus_data_contract, + block_number: int, +): + address_manager_address = _call_at_block( + consensus_data_contract.functions.addressManager(), block_number + ) + return self.w3.eth.contract( + address=address_manager_address, abi=ADDRESS_MANAGER_ABI + ) + + +def _resolve_contract( + self: GenLayerClient, + address_manager, + name: str, + abi: List[dict], + block_number: int, +): + contract_address = _call_at_block( + address_manager.functions.getAddressNonZero(name), block_number + ) + return self.w3.eth.contract(address=contract_address, abi=abi) + + +def _read_round_validators( + big_rounds_contract, + transaction_hash: _Hash32, + round_number: int, + validators_count: int, + block_number: int, +) -> List[Address]: + validators: List[Address] = [] + for offset in range(0, validators_count, TRANSACTION_ARRAY_PAGE_SIZE): + page, total = _call_at_block( + big_rounds_contract.functions.getRoundValidatorsPaged( + transaction_hash, + round_number, + offset, + TRANSACTION_ARRAY_PAGE_SIZE, + ), + block_number, + ) + if total != validators_count: + raise GenLayerError( + "Inconsistent transaction committee size at fixed block " + f"{block_number}: expected {validators_count}, got {total}" + ) + validators.extend(page) + + if len(validators) != validators_count: + raise GenLayerError( + "Incomplete transaction committee at fixed block " + f"{block_number}: expected {validators_count}, got {len(validators)}" + ) + return validators + + +def _read_consumed_validators( + big_rounds_contract, + transaction_hash: _Hash32, + validators_count: int, + block_number: int, +) -> List[Address]: + validators: List[Address] = [] + for offset in range(0, validators_count, TRANSACTION_ARRAY_PAGE_SIZE): + page, total = _call_at_block( + big_rounds_contract.functions.getConsumedValidatorsPaged( + transaction_hash, + offset, + TRANSACTION_ARRAY_PAGE_SIZE, + ), + block_number, + ) + if total != validators_count: + raise GenLayerError( + "Inconsistent consumed-validator count at fixed block " + f"{block_number}: expected {validators_count}, got {total}" + ) + validators.extend(page) + + if len(validators) != validators_count: + raise GenLayerError( + "Incomplete consumed-validator set at fixed block " + f"{block_number}: expected {validators_count}, got {len(validators)}" + ) + return validators + + +def _read_train_transaction_data( + self: GenLayerClient, + consensus_data_contract, + transaction_hash: _Hash32, + block_number: int, +): + """Compose one bounded transaction snapshot from train read surfaces.""" + address_manager = _address_manager(self, consensus_data_contract, block_number) + big_rounds = _resolve_contract( + self, + address_manager, + "ConsensusDataBigRounds", + CONSENSUS_DATA_BIG_ROUNDS_ABI, + block_number, + ) + transaction_manager = _resolve_contract( + self, + address_manager, + "TransactionManager", + TRANSACTION_MANAGER_READ_ABI, + block_number, + ) + rounds_storage = _resolve_contract( + self, + address_manager, + "RoundsStorage", + ROUNDS_STORAGE_READ_ABI, + block_number, + ) + + tx_data = _call_at_block( + big_rounds.functions.getStoredTransactionDataLight(transaction_hash), + block_number, + ) + last_round = tx_data[21] + round_number = last_round[0] + validators_count = last_round[7] + validators = _read_round_validators( + big_rounds, + transaction_hash, + round_number, + validators_count, + block_number, + ) + consumed_validators = _read_consumed_validators( + big_rounds, + transaction_hash, + tx_data[22], + block_number, + ) + validator_votes = _call_at_block( + rounds_storage.functions.getValidatorVotes(transaction_hash, round_number), + block_number, + ) + validator_votes_hash = _call_at_block( + rounds_storage.functions.getValidatorVotesHash(transaction_hash, round_number), + block_number, + ) + validator_result_hash = _call_at_block( + rounds_storage.functions.getValidatorResultHash(transaction_hash, round_number), + block_number, + ) + tx_execution_result = _call_at_block( + transaction_manager.functions.getTxExecutionResult(transaction_hash), + block_number, + ) + num_of_initial_validators = _call_at_block( + transaction_manager.functions.getNumOfInitialValidators(transaction_hash), + block_number, + ) + + for label, values in ( + ("validator votes", validator_votes), + ("validator vote hashes", validator_votes_hash), + ("validator result hashes", validator_result_hash), + ): + if len(values) != validators_count: + raise GenLayerError( + f"Incomplete {label} at fixed block {block_number}: " + f"expected {validators_count}, got {len(values)}" + ) + + return ( + tx_data, + validators, + validator_votes, + validator_votes_hash, + validator_result_hash, + consumed_validators, + tx_execution_result, + num_of_initial_validators, + ) + + +def _read_transaction_lifecycle( + consensus_data_contract, + transaction_hash: _Hash32, + block_number: int, + timestamp: int = 0, +) -> ProtocolTransactionLifecycle: + lifecycle = _call_at_block( + consensus_data_contract.functions.getTransactionLifecycle( + transaction_hash, timestamp + ), + block_number, + ) + stored_status, resolution, latest_decision, decision_active = lifecycle + projected_status = resolution[2] + resolution_action = resolution[3] + resolution_source = resolution[6] + return { + "stored_status": int(stored_status), + "stored_status_name": PROTOCOL_TRANSACTION_STATUS_NUMBER_TO_NAME[ + str(stored_status) + ], + "projected_status": int(projected_status), + "projected_status_name": PROTOCOL_TRANSACTION_STATUS_NUMBER_TO_NAME[ + str(projected_status) + ], + "resolution_action": int(resolution_action), + "resolution_action_name": RESOLUTION_ACTION_NUMBER_TO_NAME[ + str(resolution_action) + ], + "resolution_source": int(resolution_source), + "resolution_source_name": RESOLUTION_SOURCE_NUMBER_TO_NAME[ + str(resolution_source) + ], + "decision_id": str(latest_decision[1]) if decision_active else None, + "decision_active": bool(decision_active), + "evaluated_at": int(resolution[17]), + } + + +def _decode_rpc_transaction_lifecycle(result: Any) -> ProtocolTransactionLifecycle: + if not isinstance(result, dict): + raise GenLayerError("gen_getTransactionLifecycle returned no lifecycle object") + + def code(key: str) -> int: + value = result.get(key) + if isinstance(value, bool) or not isinstance(value, int): + raise GenLayerError( + f"gen_getTransactionLifecycle returned invalid {key}: {value!r}" + ) + return value + + stored_status = code("storedStatusCode") + projected_status = code("projectedStatusCode") + resolution_action = code("resolutionActionCode") + resolution_source = code("resolutionSourceCode") + try: + stored_status_name = PROTOCOL_TRANSACTION_STATUS_NUMBER_TO_NAME[ + str(stored_status) + ] + projected_status_name = PROTOCOL_TRANSACTION_STATUS_NUMBER_TO_NAME[ + str(projected_status) + ] + resolution_action_name = RESOLUTION_ACTION_NUMBER_TO_NAME[ + str(resolution_action) + ] + resolution_source_name = RESOLUTION_SOURCE_NUMBER_TO_NAME[ + str(resolution_source) + ] + except KeyError as exc: + raise GenLayerError( + f"gen_getTransactionLifecycle returned unknown protocol ordinal: {exc.args[0]}" + ) from exc + + wire_names = { + "storedStatus": stored_status_name.value, + "projectedStatus": projected_status_name.value, + "resolutionAction": resolution_action_name.value, + "resolutionSource": resolution_source_name.value, + } + for key, enum_value in wire_names.items(): + expected = enum_value + if result.get(key) != expected: + raise GenLayerError( + f"gen_getTransactionLifecycle returned inconsistent {key}: " + f"expected {expected!r}, got {result.get(key)!r}" + ) + + decision_active = result.get("decisionActive") + if not isinstance(decision_active, bool): + raise GenLayerError( + "gen_getTransactionLifecycle returned invalid decisionActive" + ) + decision_id = result.get("decisionId") + if decision_id is not None and ( + not isinstance(decision_id, str) or not decision_id.isdigit() + ): + raise GenLayerError("gen_getTransactionLifecycle returned invalid decisionId") + if decision_active != (decision_id is not None): + raise GenLayerError( + "gen_getTransactionLifecycle returned inconsistent decision identity" + ) + evaluated_at = result.get("evaluatedAt") + if isinstance(evaluated_at, bool) or not isinstance(evaluated_at, int): + raise GenLayerError("gen_getTransactionLifecycle returned invalid evaluatedAt") + + return { + "stored_status": stored_status, + "stored_status_name": stored_status_name, + "projected_status": projected_status, + "projected_status_name": projected_status_name, + "resolution_action": resolution_action, + "resolution_action_name": resolution_action_name, + "resolution_source": resolution_source, + "resolution_source_name": resolution_source_name, + "decision_id": decision_id, + "decision_active": decision_active, + "evaluated_at": evaluated_at, + } + + +_METHOD_NOT_FOUND_CODE = -32601 +_METHOD_NOT_FOUND_MESSAGES = ( + "method not found", + "does not exist", + "method not supported", +) + + +def _is_method_not_found_error(error: Any) -> bool: + """Recognize only an explicit JSON-RPC missing-method response.""" + seen = set() + current = error + while current is not None and id(current) not in seen: + seen.add(id(current)) + if isinstance(current, dict): + code = current.get("code") + message = current.get("message") + current = current.get("error") or current.get("cause") + else: + code = getattr(current, "code", None) + message = getattr(current, "message", None) or str(current) + current = getattr(current, "__cause__", None) + if code == _METHOD_NOT_FOUND_CODE: + return True + if isinstance(message, str) and any( + marker in message.lower() for marker in _METHOD_NOT_FOUND_MESSAGES + ): + return True + return False + + +def _studio_protocol_status(value: Any) -> ProtocolTransactionStatus: + """Normalize the stored status exposed by the current Studio transaction.""" + if value == "ACTIVATED": + return ProtocolTransactionStatus.PENDING + if isinstance(value, ProtocolTransactionStatus): + return value + if isinstance(value, int) or (isinstance(value, str) and value.isdigit()): + return PROTOCOL_TRANSACTION_STATUS_NUMBER_TO_NAME[str(value)] + if isinstance(value, str) and value in ProtocolTransactionStatus.__members__: + return ProtocolTransactionStatus[value] + return ProtocolTransactionStatus(value) + + +def _studio_transaction_lifecycle_fallback( + self: GenLayerClient, + transaction_hash: _Hash32, + timestamp: Optional[int], + cause: Any, +) -> ProtocolTransactionLifecycle: + """Expose only the lifecycle facts current Studio can prove.""" + try: + response = self.provider.make_request( + method="eth_getTransactionByHash", params=[transaction_hash] + ) + transaction = response.get("result") if isinstance(response, dict) else None + if not isinstance(transaction, dict): + raise ValueError("missing transaction") + status_name = _studio_protocol_status(transaction.get("status")) + status_code = int(PROTOCOL_TRANSACTION_STATUS_NAME_TO_NUMBER[status_name]) + except Exception as exc: + if isinstance(cause, BaseException): + raise cause + raise GenLayerError( + "gen_getTransactionLifecycle is unavailable and Studio did not return " + "a readable stored transaction status" + ) from exc + + return { + "stored_status": status_code, + "stored_status_name": status_name, + "projected_status": status_code, + "projected_status_name": status_name, + "resolution_action": 0, + "resolution_action_name": RESOLUTION_ACTION_NUMBER_TO_NAME["0"], + "resolution_source": 0, + "resolution_source_name": RESOLUTION_SOURCE_NUMBER_TO_NAME["0"], + "decision_id": None, + "decision_active": False, + "evaluated_at": timestamp if timestamp is not None else int(time.time()), + } + + +def get_transaction_lifecycle( + self: GenLayerClient, + transaction_hash: _Hash32, + timestamp: Optional[int] = None, +) -> ProtocolTransactionLifecycle: + """Return the raw stored/projected resolution-kernel view. + + This is an advanced protocol API. Ordinary consumers should use the + discriminated ``lifecycle`` returned by :func:`get_transaction`. + """ + + if is_studio_chain(self.chain): + tx_id = ( + Web3.to_hex(transaction_hash) + if isinstance(transaction_hash, bytes) + else transaction_hash + ) + params: Dict[str, Any] = {"txId": tx_id} + if timestamp is not None: + params["timestamp"] = timestamp + try: + response = self.provider.make_request( + method="gen_getTransactionLifecycle", params=[params] + ) + except Exception as exc: + if _is_method_not_found_error(exc): + return _studio_transaction_lifecycle_fallback( + self, tx_id, timestamp, exc + ) + raise + error = response.get("error") if isinstance(response, dict) else None + if error is not None: + if _is_method_not_found_error(error): + return _studio_transaction_lifecycle_fallback( + self, tx_id, timestamp, error + ) + raise GenLayerError(f"gen_getTransactionLifecycle failed: {error}") + return _decode_rpc_transaction_lifecycle(response.get("result")) + + consensus_data_contract = self.w3.eth.contract( + address=self.chain.consensus_data_contract["address"], + abi=self.chain.consensus_data_contract["abi"], + ) + block_number = self.w3.eth.block_number + return _read_transaction_lifecycle( + consensus_data_contract, + transaction_hash, + block_number, + timestamp if timestamp is not None else 0, + ) + + def get_transaction( self: GenLayerClient, transaction_hash: _Hash32, ) -> GenLayerTransaction: - if self.chain.id == localnet.id: + if is_studio_chain(self.chain): transaction = self.provider.make_request( method="eth_getTransactionByHash", params=[transaction_hash] )["result"] - localnet_status = ( - TransactionStatus.PENDING + protocol_status = ( + ProtocolTransactionStatus.PENDING if transaction["status"] == "ACTIVATED" else transaction["status"] ) - transaction["status"] = int(TRANSACTION_STATUS_NAME_TO_NUMBER[localnet_status]) - transaction["status_name"] = localnet_status + lifecycle = transaction_lifecycle_from_protocol_status(protocol_status) + if lifecycle["state"] == "finalized": + outcome = transaction_outcome_from_protocol_result( + transaction.get("result_name", transaction.get("result", 0)) + ) + if outcome is not None: + lifecycle["outcome"] = outcome + transaction["lifecycle"] = lifecycle + transaction.pop("status", None) + transaction.pop("status_name", None) return _decode_localnet_transaction(transaction) - # Decode for testnet — call both to get messages + txExecutionResult + # Decode one fixed-block train snapshot. The light record and split array + # reads avoid the oversized aggregate getTransactionAllData response. consensus_data_contract = self.w3.eth.contract( address=self.chain.consensus_data_contract["address"], abi=self.chain.consensus_data_contract["abi"], ) - tx_data = consensus_data_contract.functions.getTransactionData( - transaction_hash, int(time.time()) - ).call() - tx_all_data, rounds_data = consensus_data_contract.functions.getTransactionAllData( - transaction_hash - ).call() - raw_transaction = GenLayerRawTransaction.from_transaction_data(tx_data) - raw_transaction.tx_execution_result = tx_all_data[1] + block_number = self.w3.eth.block_number + ( + tx_data, + validators, + validator_votes, + validator_votes_hash, + validator_result_hash, + consumed_validators, + tx_execution_result, + num_of_initial_validators, + ) = _read_train_transaction_data( + self, + consensus_data_contract, + transaction_hash, + block_number, + ) + raw_transaction = GenLayerRawTransaction.from_transaction_data_light( + tx_data, + validators, + validator_votes, + validator_votes_hash, + validator_result_hash, + consumed_validators, + tx_execution_result, + num_of_initial_validators, + ) decoded_transaction = raw_transaction.decode() decoded_transaction["triggered_transactions"] = _decode_triggered_txs( self, decoded_transaction @@ -145,20 +745,20 @@ def get_transaction( def _decode_triggered_txs( self: GenLayerClient, tx: GenLayerTransaction ) -> List[HexStr]: - status = TRANSACTION_STATUS_NUMBER_TO_NAME[tx["status"]] - if status not in [TransactionStatus.FINALIZED, TransactionStatus.ACCEPTED]: + lifecycle = tx["lifecycle"] + state = lifecycle["state"] + accepted = state == "decided" and lifecycle.get("outcome") == "accepted" + if not accepted and state != "finalized": return [] event_hashes_by_status = { - TransactionStatus.FINALIZED: self.w3.keccak( - text="TransactionFinalized(bytes32)" - ).hex(), - TransactionStatus.ACCEPTED: self.w3.keccak( - text="TransactionAccepted(bytes32)" - ).hex(), + "finalized": self.w3.keccak(text="TransactionFinalized(bytes32)").hex(), + "accepted": self.w3.keccak(text="TransactionAccepted(bytes32)").hex(), } - def process_events_for_status(event_status: TransactionStatus) -> List[HexStr]: + def process_events_for_status( + event_status: Literal["accepted", "finalized"], + ) -> List[HexStr]: """Helper function to process events for a given status.""" event_signature_hash = event_hashes_by_status[event_status] from_block = int(tx["read_state_block_range"]["proposal_block"]) @@ -190,11 +790,11 @@ def process_events_for_status(event_status: TransactionStatus) -> List[HexStr]: triggered_txs = [] # Triggered transactions can happen on ACCEPTED or FINALIZED statuses - if status in [TransactionStatus.ACCEPTED, TransactionStatus.FINALIZED]: - triggered_txs.extend(process_events_for_status(TransactionStatus.ACCEPTED)) + if accepted or state == "finalized": + triggered_txs.extend(process_events_for_status("accepted")) - if status == TransactionStatus.FINALIZED: - triggered_txs.extend(process_events_for_status(TransactionStatus.FINALIZED)) + if state == "finalized": + triggered_txs.extend(process_events_for_status("finalized")) return triggered_txs @@ -203,7 +803,7 @@ def get_triggered_transaction_ids( self: GenLayerClient, transaction_hash: _Hash32, ) -> List[HexStr]: - if self.chain.id == localnet.id: + if is_studio_chain(self.chain): tx = get_transaction(self, transaction_hash) return tx.get("triggered_transactions", []) @@ -218,7 +818,16 @@ def debug_trace_transaction( ) -> Dict[str, Any]: response = self.provider.make_request( method="gen_dbg_traceTransaction", - params=[{"txID": Web3.to_hex(transaction_hash) if isinstance(transaction_hash, bytes) else transaction_hash, "round": round}], + params=[ + { + "txID": ( + Web3.to_hex(transaction_hash) + if isinstance(transaction_hash, bytes) + else transaction_hash + ), + "round": round, + } + ], ) return response.get("result", {}) @@ -228,7 +837,7 @@ def _simplify_transaction_receipt(tx: GenLayerTransaction) -> GenLayerTransactio Simplify transaction receipt by removing non-essential fields while preserving functionality. Removes: Binary data, internal timestamps, appeal fields, processing details, historical data - Preserves: Transaction IDs, status, execution results, node configs, readable data + Preserves: Transaction IDs, lifecycle, execution results, node configs, readable data """ simplified_tx = tx.copy() diff --git a/genlayer_py/transactions/fees.py b/genlayer_py/transactions/fees.py index e05c529..1831ddb 100644 --- a/genlayer_py/transactions/fees.py +++ b/genlayer_py/transactions/fees.py @@ -1,7 +1,7 @@ from __future__ import annotations from enum import IntEnum -from typing import Any, Optional, TypedDict, Union +from typing import Any, NotRequired, Optional, TypedDict, Union from eth_abi import encode as abi_encode from eth_typing import HexStr @@ -19,9 +19,9 @@ class MessageType(IntEnum): class FeesDistributionInput(TypedDict, total=False): leaderTimeunitsAllocation: BigNumberish - leader_timeunits_allocation: BigNumberish + leader_time_units_allocation: BigNumberish validatorTimeunitsAllocation: BigNumberish - validator_timeunits_allocation: BigNumberish + validator_time_units_allocation: BigNumberish appealRounds: BigNumberish appeal_rounds: BigNumberish executionBudgetPerRound: BigNumberish @@ -54,14 +54,20 @@ class FeesDistribution(TypedDict): class InternalMessageFeeParamsInput(TypedDict, total=False): leaderTimeunitsAllocation: BigNumberish - leader_timeunits_allocation: BigNumberish + leader_time_units_allocation: BigNumberish validatorTimeunitsAllocation: BigNumberish - validator_timeunits_allocation: BigNumberish + validator_time_units_allocation: BigNumberish appealRounds: BigNumberish appeal_rounds: BigNumberish executionBudgetPerRound: BigNumberish execution_budget_per_round: BigNumberish rotations: list[BigNumberish] + maxPriceGenPerTimeUnit: BigNumberish + max_price_gen_per_time_unit: BigNumberish + storageFeeMaxGasPrice: BigNumberish + storage_fee_max_gas_price: BigNumberish + receiptFeeMaxGasPrice: BigNumberish + receipt_fee_max_gas_price: BigNumberish class ExternalMessageFeeParamsInput(TypedDict, total=False): @@ -110,6 +116,7 @@ class FeePolicyQuote(TypedDict): storageUnitPrice: int receiptGasPrice: int executionBudgetFloor: int + timeUnitOverlayBps: NotRequired[int] class FeeEstimateOptions(FeesDistributionInput, total=False): @@ -131,6 +138,7 @@ class TransactionFeeEstimate(TypedDict, total=False): fee_value: int policy: FeePolicyQuote observed: dict[str, int] + simulation: Any class SimulationFeeEstimateOptions(FeeEstimateOptions, total=False): @@ -153,9 +161,16 @@ class NormalizedTransactionFees(TypedDict): MESSAGE_ALLOCATION_ROOT_PARENT_INDEX = (1 << 256) - 1 -CALL_KEY_WILDCARD = b"\x00" * 32 +# Wildcard sentinel = keccak256 of empty bytes, untagged. Reserved: it can never be a +# derived key — short names (<32B) are left-aligned with a zero tail byte, long names +# get the low bit forced to 1, and this hash has neither. +CALL_KEY_WILDCARD = bytes.fromhex( + "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" +) +# Empty method name derives bytes32(0); GenVM emits it for deploy and emit_transfer. CALL_KEY_UNNAMED = HexStr("0x" + ("0" * 64)) -CALL_KEY_DEPLOY = CALL_KEY_UNNAMED +DEPLOY_CALL_KEY = CALL_KEY_UNNAMED +CALL_KEY_DEPLOY = DEPLOY_CALL_KEY FEES_DISTRIBUTION_ABI_TYPE = ( "(uint256,uint256,uint256,uint256,uint256,uint256,uint256[],uint256,uint256,uint256)" @@ -193,13 +208,20 @@ class NormalizedTransactionFees(TypedDict): DEFAULT_LEADER_TIMEUNITS_ALLOCATION = 100 DEFAULT_VALIDATOR_TIMEUNITS_ALLOCATION = 200 DEFAULT_TRANSACTION_EXECUTION_BUDGET_PER_ROUND = 500_000 +# Provisional heuristic sized ~20x observed dev-env consumption (~5M gas-equivalent). +# TODO(data): replace with telemetry-derived default (p99 x margin) once fee consumption telemetry is collected. +DEFAULT_TRANSACTION_EXECUTION_GAS = 100_000_000 +DEFAULT_PARENT_MESSAGE_RECEIPT_HEADROOM = 10_000 MIN_RECEIPT_BYTES = 512 DEFAULT_RECEIPT_SLOTS_CHANGED = 7 DEFAULT_INTRINSIC_GAS = 21_000 DEFAULT_BOOTLOADER_OVERHEAD = 60_000 DEFAULT_FIXED_PROPOSE_RECEIPT_GAS = 210_000 +DEFAULT_FIXED_MESSAGE_REVEAL_GAS = 100_000 DEFAULT_GAS_PER_CHANGED_SLOT = 1_000 DEFAULT_CALLDATA_GAS_PER_BYTE = 16 +DEFAULT_MESSAGE_REVEAL_LENGTH_SLOTS = 32 +DEFAULT_NONDET_OUTPUT_LENGTH_BYTES = 32 ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" VALIDATORS_PER_ROUND = [ @@ -305,6 +327,10 @@ def derive_external_message_call_key( return _bytes_to_padded_call_key(calldata[:4]) +def deploy_call_key() -> HexStr: + return DEPLOY_CALL_KEY + + def _normalize_message_type(value: Union[MessageType, int, str]) -> int: if isinstance(value, MessageType): return int(value) @@ -337,19 +363,17 @@ def _normalize_rotations( return normalized -def create_fees_distribution( - fee_distribution: Optional[FeesDistributionInput] = None, +def _create_fees_distribution( + fee_distribution: Optional[FeesDistributionInput], + appeal_rounds: int, + rotations: list[int], ) -> FeesDistribution: - appeal_rounds = to_uint( - _get(fee_distribution, "appealRounds", "appeal_rounds"), - "fees.distribution.appealRounds", - ) return { "leaderTimeunitsAllocation": to_uint( _get( fee_distribution, "leaderTimeunitsAllocation", - "leader_timeunits_allocation", + "leader_time_units_allocation", ), "fees.distribution.leaderTimeunitsAllocation", ), @@ -357,7 +381,7 @@ def create_fees_distribution( _get( fee_distribution, "validatorTimeunitsAllocation", - "validator_timeunits_allocation", + "validator_time_units_allocation", ), "fees.distribution.validatorTimeunitsAllocation", ), @@ -378,11 +402,7 @@ def create_fees_distribution( _get(fee_distribution, "totalMessageFees", "total_message_fees"), "fees.distribution.totalMessageFees", ), - "rotations": _normalize_rotations( - _get(fee_distribution, "rotations"), - appeal_rounds, - "fees.distribution.rotations", - ), + "rotations": rotations, "maxPriceGenPerTimeUnit": to_uint( _get( fee_distribution, @@ -410,6 +430,50 @@ def create_fees_distribution( } +def create_fees_distribution( + fee_distribution: Optional[FeesDistributionInput] = None, +) -> FeesDistribution: + appeal_rounds = to_uint( + _get(fee_distribution, "appealRounds", "appeal_rounds"), + "fees.distribution.appealRounds", + ) + rotations = _normalize_rotations( + _get(fee_distribution, "rotations"), + appeal_rounds, + "fees.distribution.rotations", + ) + return _create_fees_distribution(fee_distribution, appeal_rounds, rotations) + + +def create_top_up_fees_distribution( + fee_distribution: Optional[FeesDistributionInput] = None, +) -> FeesDistribution: + """Normalize a Consensus top-up delta without resubmitting its schedule. + + Existing fee-aware transactions use appealRounds=0/rotations=[]. An + explicit non-empty schedule remains valid for first-time fee initialization. + """ + appeal_rounds = to_uint( + _get(fee_distribution, "appealRounds", "appeal_rounds"), + "fees.distribution.appealRounds", + ) + raw_rotations = _get(fee_distribution, "rotations") + if raw_rotations is None or len(raw_rotations) == 0: + if appeal_rounds != 0: + raise ValueError( + "fees.distribution.rotations must contain appealRounds + 1 " + "entries when appealRounds is non-zero." + ) + rotations = [] + else: + rotations = _normalize_rotations( + raw_rotations, + appeal_rounds, + "fees.distribution.rotations", + ) + return _create_fees_distribution(fee_distribution, appeal_rounds, rotations) + + def encode_internal_message_fee_params( params: Optional[InternalMessageFeeParamsInput] = None, ) -> HexStr: @@ -418,14 +482,14 @@ def encode_internal_message_fee_params( "internalMessageFeeParams.appealRounds", ) encoded = abi_encode( - ("(uint256,uint256,uint256,uint256,uint256[])",), + ("(uint256,uint256,uint256,uint256,uint256[],uint256,uint256,uint256)",), ( ( to_uint( _get( params, "leaderTimeunitsAllocation", - "leader_timeunits_allocation", + "leader_time_units_allocation", ), "internalMessageFeeParams.leaderTimeunitsAllocation", ), @@ -433,7 +497,7 @@ def encode_internal_message_fee_params( _get( params, "validatorTimeunitsAllocation", - "validator_timeunits_allocation", + "validator_time_units_allocation", ), "internalMessageFeeParams.validatorTimeunitsAllocation", ), @@ -451,6 +515,30 @@ def encode_internal_message_fee_params( appeal_rounds, "internalMessageFeeParams.rotations", ), + to_uint( + _get( + params, + "maxPriceGenPerTimeUnit", + "max_price_gen_per_time_unit", + ), + "internalMessageFeeParams.maxPriceGenPerTimeUnit", + ), + to_uint( + _get( + params, + "storageFeeMaxGasPrice", + "storage_fee_max_gas_price", + ), + "internalMessageFeeParams.storageFeeMaxGasPrice", + ), + to_uint( + _get( + params, + "receiptFeeMaxGasPrice", + "receipt_fee_max_gas_price", + ), + "internalMessageFeeParams.receiptFeeMaxGasPrice", + ), ), ), ) @@ -635,6 +723,10 @@ def extract_studio_fee_policy(config: Any) -> FeePolicyQuote: policy.get("receiptGasPrice"), "policy.receiptGasPrice", ) + time_unit_overlay_bps = _int_from_unknown( + policy.get("timeUnitOverlayBps", 0), + "policy.timeUnitOverlayBps", + ) intrinsic_gas = _int_from_unknown( policy.get("intrinsicGas", DEFAULT_INTRINSIC_GAS), "policy.intrinsicGas", @@ -655,6 +747,10 @@ def extract_studio_fee_policy(config: Any) -> FeePolicyQuote: policy.get("fixedProposeReceiptGas", DEFAULT_FIXED_PROPOSE_RECEIPT_GAS), "policy.fixedProposeReceiptGas", ) + fixed_message_reveal_gas = _int_from_unknown( + policy.get("fixedMessageRevealGas", DEFAULT_FIXED_MESSAGE_REVEAL_GAS), + "policy.fixedMessageRevealGas", + ) explicit_budget_floor = policy.get( "messageFeeParamsBudgetFloor", config.get("messageFeeParamsBudgetFloor"), @@ -670,8 +766,12 @@ def extract_studio_fee_policy(config: Any) -> FeePolicyQuote: fixed_propose_receipt_gas + intrinsic_gas + bootloader_overhead - + (MIN_RECEIPT_BYTES * calldata_gas_per_byte) + (DEFAULT_RECEIPT_SLOTS_CHANGED * gas_per_changed_slot) + + fixed_message_reveal_gas + + intrinsic_gas + + bootloader_overhead + + (DEFAULT_MESSAGE_REVEAL_LENGTH_SLOTS * gas_per_changed_slot) + + (DEFAULT_NONDET_OUTPUT_LENGTH_BYTES * calldata_gas_per_byte) ) ) @@ -687,6 +787,7 @@ def extract_studio_fee_policy(config: Any) -> FeePolicyQuote: "storageUnitPrice": storage_unit_price, "receiptGasPrice": receipt_gas_price, "executionBudgetFloor": execution_budget_floor, + "timeUnitOverlayBps": time_unit_overlay_bps, } @@ -703,6 +804,7 @@ def _default_execution_budget_per_round(policy: FeePolicyQuote) -> int: return max( DEFAULT_TRANSACTION_EXECUTION_BUDGET_PER_ROUND, policy["executionBudgetFloor"], + policy["receiptGasPrice"] * DEFAULT_TRANSACTION_EXECUTION_GAS, ) @@ -856,7 +958,7 @@ def observed_simulation_fee_usage( observed_execution_budget = execution_fee_consumed + execution_fee_report_total recommended_execution_budget = ( max( - _default_execution_budget_per_round(policy), + policy["executionBudgetFloor"], _with_cap_headroom(observed_execution_budget, execution_headroom_bps), ) if observed_execution_budget > 0 @@ -967,6 +1069,7 @@ def transaction_fee_estimate_from_studio_estimate( "feeValue": to_uint(fee_value, "recommendedPreset.feeValue"), "fee_value": to_uint(fee_value, "recommendedPreset.feeValue"), "policy": policy, + "simulation": simulation, "observed": observed_simulation_fee_usage( {"simulation": simulation}, policy, @@ -1052,30 +1155,63 @@ def build_estimated_fees_options_from_simulation( def build_estimated_fees_distribution( options: Optional[FeeEstimateOptions], policy: FeePolicyQuote, + default_consensus_max_rotations: BigNumberish, ) -> FeesDistribution: headroom_bps = to_uint( _get(options, "priceCapHeadroomBps", "price_cap_headroom_bps"), "priceCapHeadroomBps", DEFAULT_PRICE_CAP_HEADROOM_BPS, ) - execution_budget_default = _default_execution_budget_per_round(policy) + base_execution_budget_default = _default_execution_budget_per_round(policy) total_message_fees = _get(options, "totalMessageFees", "total_message_fees") message_allocations = _get(options, "messageAllocations", "message_allocations") + normalized_message_allocations = ( + normalize_message_fee_allocations(message_allocations) + if message_allocations is not None + else None + ) if total_message_fees is None and message_allocations is not None: total_message_fees = sum( allocation["budget"] - for allocation in normalize_message_fee_allocations(message_allocations) + for allocation in normalized_message_allocations or [] if allocation["messageType"] == int(MessageType.External) or allocation["parentIndex"] == MESSAGE_ALLOCATION_ROOT_PARENT_INDEX ) + emits_messages = ( + ( + normalized_message_allocations is not None + and len(normalized_message_allocations) > 0 + ) + or ( + total_message_fees is not None + and to_uint(total_message_fees, "totalMessageFees") > 0 + ) + ) + execution_budget_default = ( + base_execution_budget_default + + policy["receiptGasPrice"] * DEFAULT_PARENT_MESSAGE_RECEIPT_HEADROOM + if emits_messages + else base_execution_budget_default + ) + appeal_rounds = to_uint( + _get(options, "appealRounds", "appeal_rounds"), + "appealRounds", + ) + rotations = _get(options, "rotations") + if rotations is None: + default_rotations = to_uint( + default_consensus_max_rotations, + "defaultConsensusMaxRotations", + ) + rotations = [default_rotations] * (appeal_rounds + 1) return create_fees_distribution( { "leaderTimeunitsAllocation": _get( options, "leaderTimeunitsAllocation", - "leader_timeunits_allocation", + "leader_time_units_allocation", default=DEFAULT_LEADER_TIMEUNITS_ALLOCATION if policy["enabled"] else 0, @@ -1083,12 +1219,12 @@ def build_estimated_fees_distribution( "validatorTimeunitsAllocation": _get( options, "validatorTimeunitsAllocation", - "validator_timeunits_allocation", + "validator_time_units_allocation", default=DEFAULT_VALIDATOR_TIMEUNITS_ALLOCATION if policy["enabled"] else 0, ), - "appealRounds": _get(options, "appealRounds", "appeal_rounds"), + "appealRounds": appeal_rounds, "executionBudgetPerRound": _get( options, "executionBudgetPerRound", @@ -1101,7 +1237,7 @@ def build_estimated_fees_distribution( "execution_consumed", ), "totalMessageFees": total_message_fees, - "rotations": _get(options, "rotations"), + "rotations": rotations, "maxPriceGenPerTimeUnit": _get( options, "maxPriceGenPerTimeUnit", @@ -1143,15 +1279,25 @@ def _validator_index(num_of_validators: int) -> int: def _calculate_fee_for_round( num_of_validators: int, rotations: int, - leader_timeunits_allocation: int, - validator_timeunits_allocation: int, + leader_time_units_allocation: int, + validator_time_units_allocation: int, ) -> int: return rotations * ( - leader_timeunits_allocation - + num_of_validators * validator_timeunits_allocation + leader_time_units_allocation + + num_of_validators * validator_time_units_allocation ) +def _validators_per_round_safe(round_index: int) -> int: + return VALIDATORS_PER_ROUND[ + min(max(0, int(round_index)), len(VALIDATORS_PER_ROUND) - 1) + ] + + +def _successful_appeal_profit(appeal_bond: int) -> int: + return appeal_bond + appeal_bond // 2 + + def calculate_local_round_fees( distribution: FeesDistribution, num_of_initial_validators: int, @@ -1176,10 +1322,8 @@ def calculate_local_round_fees( raise ValueError("MaxPriceExceeded") start_index = _validator_index(num_of_initial_validators) - if start_index + distribution["appealRounds"] * 2 >= len(VALIDATORS_PER_ROUND): - raise ValueError("InvalidNumOfValidators") - total = _calculate_fee_for_round( + taxable_work = _calculate_fee_for_round( VALIDATORS_PER_ROUND[start_index], distribution["rotations"][0] + 1, distribution["leaderTimeunitsAllocation"], @@ -1194,22 +1338,51 @@ def calculate_local_round_fees( elif offset % 2 == 1: rotations_this_round = 1 - total += _calculate_fee_for_round( - VALIDATORS_PER_ROUND[start_index + offset], + # Consensus indexes appeal/next-normal committees by absolute round + # and saturates at the published ladder. Only round zero uses the + # caller-selected initial committee. + taxable_work += _calculate_fee_for_round( + _validators_per_round_safe(offset), rotations_this_round, distribution["leaderTimeunitsAllocation"], distribution["validatorTimeunitsAllocation"], ) - if policy["genPerTimeUnit"] > 0: - total *= policy["genPerTimeUnit"] + price_cap = distribution["maxPriceGenPerTimeUnit"] + if price_cap > 0: + taxable_work *= price_cap + + appeal_profit_reserve = 0 + for appeal_ordinal in range(distribution["appealRounds"]): + next_normal_bond = _calculate_fee_for_round( + _validators_per_round_safe((appeal_ordinal + 1) * 2), + distribution["rotations"][appeal_ordinal + 1] + 1, + distribution["leaderTimeunitsAllocation"], + distribution["validatorTimeunitsAllocation"], + ) + if price_cap > 0: + next_normal_bond *= price_cap + appeal_profit_reserve += _successful_appeal_profit(next_normal_bond) + + overlay_bps = int(policy.get("timeUnitOverlayBps", 0)) + if overlay_bps < 0 or overlay_bps >= 10_000: + raise ValueError("InvalidTimeUnitOverlayBps") + overlay = ( + taxable_work * overlay_bps // (10_000 - overlay_bps) + if overlay_bps > 0 + else 0 + ) leader_rounds = sum( rotations + 1 for rotations in distribution["rotations"] ) + distribution["appealRounds"] - total += distribution["executionBudgetPerRound"] * leader_rounds - return total + return ( + taxable_work + + appeal_profit_reserve + + overlay + + distribution["executionBudgetPerRound"] * leader_rounds + ) def build_add_transaction_params_tuple( diff --git a/genlayer_py/types/__init__.py b/genlayer_py/types/__init__.py index 04e4a64..f7021f9 100644 --- a/genlayer_py/types/__init__.py +++ b/genlayer_py/types/__init__.py @@ -2,18 +2,27 @@ from .transactions import ( GenLayerTransaction, GenLayerRawTransaction, - TransactionStatus, + TransactionLifecycle, + TransactionProcessingPhase, + TransactionDecisionOutcome, + ProcessingTransactionLifecycle, + DecidedTransactionLifecycle, + FinalizedTransactionLifecycle, + CanceledTransactionLifecycle, TransactionHashVariant, TRANSACTION_RESULT_NAME_TO_NUMBER, TRANSACTION_RESULT_NUMBER_TO_NAME, ExecutionResult, + VoteType, EXECUTION_RESULT_NUMBER_TO_NAME, - TRANSACTION_STATUS_NAME_TO_NUMBER, - TRANSACTION_STATUS_NUMBER_TO_NAME, VOTE_TYPE_NAME_TO_NUMBER, VOTE_TYPE_NUMBER_TO_NAME, - DECIDED_STATES, - is_decided_state, ) -from .chain import Chain, NativeCurrency, ContractInfo, SimpleContractInfo, GenLayerChain +from .chain import ( + Chain, + NativeCurrency, + ContractInfo, + SimpleContractInfo, + GenLayerChain, +) from .contracts import ContractSchema, SimConfig diff --git a/genlayer_py/types/transactions.py b/genlayer_py/types/transactions.py index f73a85a..01e489f 100644 --- a/genlayer_py/types/transactions.py +++ b/genlayer_py/types/transactions.py @@ -3,7 +3,17 @@ import base64 from genlayer_py.abi import calldata from enum import Enum -from typing import Dict, Optional, Any, TypedDict, List, Tuple, Literal, Union +from typing import ( + Dict, + Optional, + Any, + TypedDict, + List, + Tuple, + Literal, + Union, + NotRequired, +) from eth_typing import Address, HexStr from web3 import Web3 from dataclasses import dataclass @@ -11,73 +21,215 @@ from genlayer_py.consensus.consensus_main import decode_tx_data -class TransactionStatus(str, Enum): - """Status of a GenLayer transaction in the consensus lifecycle.""" - UNINITIALIZED = "UNINITIALIZED" - PENDING = "PENDING" - PROPOSING = "PROPOSING" - COMMITTING = "COMMITTING" - REVEALING = "REVEALING" - ACCEPTED = "ACCEPTED" - UNDETERMINED = "UNDETERMINED" - FINALIZED = "FINALIZED" - CANCELED = "CANCELED" - APPEAL_REVEALING = "APPEAL_REVEALING" - APPEAL_COMMITTING = "APPEAL_COMMITTING" - READY_TO_FINALIZE = "READY_TO_FINALIZE" - VALIDATORS_TIMEOUT = "VALIDATORS_TIMEOUT" - LEADER_TIMEOUT = "LEADER_TIMEOUT" - - -TRANSACTION_STATUS_NUMBER_TO_NAME = { - "0": TransactionStatus.UNINITIALIZED, - "1": TransactionStatus.PENDING, - "2": TransactionStatus.PROPOSING, - "3": TransactionStatus.COMMITTING, - "4": TransactionStatus.REVEALING, - "5": TransactionStatus.ACCEPTED, - "6": TransactionStatus.UNDETERMINED, - "7": TransactionStatus.FINALIZED, - "8": TransactionStatus.CANCELED, - "9": TransactionStatus.APPEAL_REVEALING, - "10": TransactionStatus.APPEAL_COMMITTING, - "11": TransactionStatus.READY_TO_FINALIZE, - "12": TransactionStatus.VALIDATORS_TIMEOUT, - "13": TransactionStatus.LEADER_TIMEOUT, +class ProtocolTransactionStatus(str, Enum): + """Raw transaction status stored by the consensus contracts. + + This protocol enum is intentionally advanced API. Consumer-facing + transactions expose a small ``lifecycle`` value discriminated by ``state`` + instead. + """ + + UNINITIALIZED = "Uninitialized" + PENDING = "Pending" + PROPOSING = "Proposing" + COMMITTING = "Committing" + REVEALING = "Revealing" + ACCEPTED = "Accepted" + UNDETERMINED = "Undetermined" + FINALIZED = "Finalized" + CANCELED = "Canceled" + APPEAL_REVEALING = "AppealRevealing" + APPEAL_COMMITTING = "AppealCommitting" + VALIDATORS_TIMEOUT = "ValidatorsTimeout" + LEADER_TIMEOUT = "LeaderTimeout" + LEADER_REVEALING = "LeaderRevealing" + + +class ResolutionAction(str, Enum): + """Action projected by the transaction lifecycle resolution kernel.""" + + NO_OP = "NoOp" + CANCEL = "Cancel" + REPLACE_ACTOR = "ReplaceActor" + ROTATE_LEADER = "RotateLeader" + RESOLVE_APPEAL = "ResolveAppeal" + MATERIALIZE_DECISION = "MaterializeDecision" + FINALIZE = "Finalize" + + +class ResolutionSource(str, Enum): + """Protocol trigger that produced a transaction resolution plan.""" + + UNSPECIFIED = "Unspecified" + ACTIVATION_INSUFFICIENT_VALIDATORS = "ActivationInsufficientValidators" + PROPOSAL_HANGING = "ProposalHanging" + LEADER_RECEIPT_TIMEOUT = "LeaderReceiptTimeout" + COMMIT_HANGING = "CommitHanging" + LEADER_REVEAL_HANGING = "LeaderRevealHanging" + FULL_REVEAL = "FullReveal" + REVEAL_DEADLINE = "RevealDeadline" + APPEAL_COMMIT_HANGING = "AppealCommitHanging" + APPEAL_FULL_REVEAL = "AppealFullReveal" + APPEAL_REVEAL_DEADLINE = "AppealRevealDeadline" + SELECTION_DEPLETED = "SelectionDepleted" + + +RESOLUTION_ACTION_NUMBER_TO_NAME = { + "0": ResolutionAction.NO_OP, + "1": ResolutionAction.CANCEL, + "2": ResolutionAction.REPLACE_ACTOR, + "3": ResolutionAction.ROTATE_LEADER, + "4": ResolutionAction.RESOLVE_APPEAL, + "5": ResolutionAction.MATERIALIZE_DECISION, + "6": ResolutionAction.FINALIZE, } -TRANSACTION_STATUS_NAME_TO_NUMBER = { - TransactionStatus.UNINITIALIZED: "0", - TransactionStatus.PENDING: "1", - TransactionStatus.PROPOSING: "2", - TransactionStatus.COMMITTING: "3", - TransactionStatus.REVEALING: "4", - TransactionStatus.ACCEPTED: "5", - TransactionStatus.UNDETERMINED: "6", - TransactionStatus.FINALIZED: "7", - TransactionStatus.CANCELED: "8", - TransactionStatus.APPEAL_REVEALING: "9", - TransactionStatus.APPEAL_COMMITTING: "10", - TransactionStatus.READY_TO_FINALIZE: "11", - TransactionStatus.VALIDATORS_TIMEOUT: "12", - TransactionStatus.LEADER_TIMEOUT: "13", +RESOLUTION_SOURCE_NUMBER_TO_NAME = { + str(number): source for number, source in enumerate(ResolutionSource) } -DECIDED_STATES = [ - TransactionStatus.ACCEPTED, - TransactionStatus.UNDETERMINED, - TransactionStatus.LEADER_TIMEOUT, - TransactionStatus.VALIDATORS_TIMEOUT, - TransactionStatus.CANCELED, - TransactionStatus.FINALIZED + +TransactionProcessingPhase = Literal[ + "uninitialized", + "pending", + "proposing", + "committing", + "revealing", + "appeal_revealing", + "appeal_committing", + "leader_revealing", +] +TransactionDecisionOutcome = Literal[ + "accepted", "undetermined", "validators_timeout", "leader_timeout" ] -def is_decided_state(status: str) -> bool: - return status in [TRANSACTION_STATUS_NAME_TO_NUMBER[state] for state in DECIDED_STATES] + +class ProcessingTransactionLifecycle(TypedDict): + state: Literal["processing"] + phase: TransactionProcessingPhase + + +class DecidedTransactionLifecycle(TypedDict): + state: Literal["decided"] + outcome: TransactionDecisionOutcome + + +class FinalizedTransactionLifecycle(TypedDict): + state: Literal["finalized"] + outcome: NotRequired[TransactionDecisionOutcome] + + +class CanceledTransactionLifecycle(TypedDict): + state: Literal["canceled"] + + +TransactionLifecycle = Union[ + ProcessingTransactionLifecycle, + DecidedTransactionLifecycle, + FinalizedTransactionLifecycle, + CanceledTransactionLifecycle, +] + + +class ProtocolTransactionLifecycle(TypedDict): + """Advanced resolution-kernel view for one fixed block snapshot.""" + + stored_status: int + stored_status_name: ProtocolTransactionStatus + projected_status: int + projected_status_name: ProtocolTransactionStatus + resolution_action: int + resolution_action_name: ResolutionAction + resolution_source: int + resolution_source_name: ResolutionSource + decision_id: Optional[str] + decision_active: bool + evaluated_at: int + + +# Current train protocol ordinals. Finalization readiness is a resolution +# verdict, not a stored or projected transaction status. +PROTOCOL_TRANSACTION_STATUS_NUMBER_TO_NAME = { + "0": ProtocolTransactionStatus.UNINITIALIZED, + "1": ProtocolTransactionStatus.PENDING, + "2": ProtocolTransactionStatus.PROPOSING, + "3": ProtocolTransactionStatus.COMMITTING, + "4": ProtocolTransactionStatus.REVEALING, + "5": ProtocolTransactionStatus.ACCEPTED, + "6": ProtocolTransactionStatus.UNDETERMINED, + "7": ProtocolTransactionStatus.FINALIZED, + "8": ProtocolTransactionStatus.CANCELED, + "9": ProtocolTransactionStatus.APPEAL_REVEALING, + "10": ProtocolTransactionStatus.APPEAL_COMMITTING, + "11": ProtocolTransactionStatus.VALIDATORS_TIMEOUT, + "12": ProtocolTransactionStatus.LEADER_TIMEOUT, + "13": ProtocolTransactionStatus.LEADER_REVEALING, +} + +PROTOCOL_TRANSACTION_STATUS_NAME_TO_NUMBER = { + status: str(number) for number, status in enumerate(ProtocolTransactionStatus) +} + +_PROCESSING_PHASE_BY_PROTOCOL_STATUS: Dict[ + ProtocolTransactionStatus, TransactionProcessingPhase +] = { + ProtocolTransactionStatus.UNINITIALIZED: "uninitialized", + ProtocolTransactionStatus.PENDING: "pending", + ProtocolTransactionStatus.PROPOSING: "proposing", + ProtocolTransactionStatus.COMMITTING: "committing", + ProtocolTransactionStatus.REVEALING: "revealing", + ProtocolTransactionStatus.APPEAL_REVEALING: "appeal_revealing", + ProtocolTransactionStatus.APPEAL_COMMITTING: "appeal_committing", + ProtocolTransactionStatus.LEADER_REVEALING: "leader_revealing", +} + + +def transaction_lifecycle_from_protocol_status( + status: Union[int, str, ProtocolTransactionStatus], +) -> TransactionLifecycle: + """Map every stored protocol status to the stable consumer lifecycle.""" + + if isinstance(status, ProtocolTransactionStatus): + protocol_status = status + elif isinstance(status, int) or (isinstance(status, str) and status.isdigit()): + try: + protocol_status = PROTOCOL_TRANSACTION_STATUS_NUMBER_TO_NAME[str(status)] + except KeyError as exc: + raise ValueError(f"Unknown protocol transaction status: {status}") from exc + else: + try: + status_text = str(status) + protocol_status = ( + ProtocolTransactionStatus[status_text] + if status_text in ProtocolTransactionStatus.__members__ + else ProtocolTransactionStatus(status_text) + ) + except ValueError as exc: + raise ValueError(f"Unknown protocol transaction status: {status}") from exc + + if protocol_status in _PROCESSING_PHASE_BY_PROTOCOL_STATUS: + return { + "state": "processing", + "phase": _PROCESSING_PHASE_BY_PROTOCOL_STATUS[protocol_status], + } + if protocol_status == ProtocolTransactionStatus.ACCEPTED: + return {"state": "decided", "outcome": "accepted"} + if protocol_status == ProtocolTransactionStatus.UNDETERMINED: + return {"state": "decided", "outcome": "undetermined"} + if protocol_status == ProtocolTransactionStatus.VALIDATORS_TIMEOUT: + return {"state": "decided", "outcome": "validators_timeout"} + if protocol_status == ProtocolTransactionStatus.LEADER_TIMEOUT: + return {"state": "decided", "outcome": "leader_timeout"} + if protocol_status == ProtocolTransactionStatus.FINALIZED: + return {"state": "finalized"} + if protocol_status == ProtocolTransactionStatus.CANCELED: + return {"state": "canceled"} + raise AssertionError(f"Unmapped protocol transaction status: {protocol_status}") class TransactionResult(str, Enum): """Consensus voting result across validators.""" + IDLE = "IDLE" AGREE = "AGREE" DISAGREE = "DISAGREE" @@ -86,68 +238,105 @@ class TransactionResult(str, Enum): NO_MAJORITY = "NO_MAJORITY" MAJORITY_AGREE = "MAJORITY_AGREE" MAJORITY_DISAGREE = "MAJORITY_DISAGREE" + MAJORITY_TIMEOUT = "MAJORITY_TIMEOUT" TRANSACTION_RESULT_NUMBER_TO_NAME = { "0": TransactionResult.IDLE, - "1": TransactionResult.AGREE, - "2": TransactionResult.DISAGREE, - "3": TransactionResult.TIMEOUT, + "1": TransactionResult.MAJORITY_AGREE, + "2": TransactionResult.MAJORITY_DISAGREE, + "3": TransactionResult.MAJORITY_TIMEOUT, "4": TransactionResult.DETERMINISTIC_VIOLATION, "5": TransactionResult.NO_MAJORITY, - "6": TransactionResult.MAJORITY_AGREE, - "7": TransactionResult.MAJORITY_DISAGREE, } TRANSACTION_RESULT_NAME_TO_NUMBER = { TransactionResult.IDLE: "0", - TransactionResult.AGREE: "1", - TransactionResult.DISAGREE: "2", - TransactionResult.TIMEOUT: "3", + TransactionResult.MAJORITY_AGREE: "1", + TransactionResult.MAJORITY_DISAGREE: "2", + TransactionResult.MAJORITY_TIMEOUT: "3", TransactionResult.DETERMINISTIC_VIOLATION: "4", TransactionResult.NO_MAJORITY: "5", - TransactionResult.MAJORITY_AGREE: "6", - TransactionResult.MAJORITY_DISAGREE: "7", } +def transaction_outcome_from_protocol_result( + result: Union[int, str, TransactionResult], +) -> Optional[TransactionDecisionOutcome]: + """Return an application outcome when a finalized record preserves one.""" + + if isinstance(result, TransactionResult): + result_name = result + elif isinstance(result, int) or (isinstance(result, str) and result.isdigit()): + result_name = TRANSACTION_RESULT_NUMBER_TO_NAME.get(str(result)) + else: + try: + result_name = TransactionResult(str(result)) + except ValueError: + result_name = None + + if result_name == TransactionResult.MAJORITY_AGREE: + return "accepted" + if result_name == TransactionResult.MAJORITY_TIMEOUT: + return "validators_timeout" + if result_name in ( + TransactionResult.MAJORITY_DISAGREE, + TransactionResult.DETERMINISTIC_VIOLATION, + TransactionResult.NO_MAJORITY, + ): + return "undetermined" + return None + + class ExecutionResult(str, Enum): """Result of contract execution by the GenVM.""" + NOT_VOTED = "NOT_VOTED" FINISHED_WITH_RETURN = "FINISHED_WITH_RETURN" FINISHED_WITH_ERROR = "FINISHED_WITH_ERROR" + TIMEOUT = "TIMEOUT" + NONDET_DISAGREE = "NONDET_DISAGREE" + DETERMINISTIC_VIOLATION = "DETERMINISTIC_VIOLATION" EXECUTION_RESULT_NUMBER_TO_NAME = { "0": ExecutionResult.NOT_VOTED, "1": ExecutionResult.FINISHED_WITH_RETURN, "2": ExecutionResult.FINISHED_WITH_ERROR, + "3": ExecutionResult.TIMEOUT, + "4": ExecutionResult.NONDET_DISAGREE, + "5": ExecutionResult.DETERMINISTIC_VIOLATION, } class VoteType(str, Enum): + """Validator execution vote recorded for a consensus round.""" + NOT_VOTED = "NOT_VOTED" - AGREE = "AGREE" - DISAGREE = "DISAGREE" + FINISHED_WITH_RETURN = "FINISHED_WITH_RETURN" + FINISHED_WITH_ERROR = "FINISHED_WITH_ERROR" TIMEOUT = "TIMEOUT" + NONDET_DISAGREE = "NONDET_DISAGREE" DETERMINISTIC_VIOLATION = "DETERMINISTIC_VIOLATION" VOTE_TYPE_NUMBER_TO_NAME = { "0": VoteType.NOT_VOTED, - "1": VoteType.AGREE, - "2": VoteType.DISAGREE, + "1": VoteType.FINISHED_WITH_RETURN, + "2": VoteType.FINISHED_WITH_ERROR, "3": VoteType.TIMEOUT, - "4": VoteType.DETERMINISTIC_VIOLATION, + "4": VoteType.NONDET_DISAGREE, + "5": VoteType.DETERMINISTIC_VIOLATION, } VOTE_TYPE_NAME_TO_NUMBER = { VoteType.NOT_VOTED: "0", - VoteType.AGREE: "1", - VoteType.DISAGREE: "2", + VoteType.FINISHED_WITH_RETURN: "1", + VoteType.FINISHED_WITH_ERROR: "2", VoteType.TIMEOUT: "3", - VoteType.DETERMINISTIC_VIOLATION: "4", + VoteType.NONDET_DISAGREE: "4", + VoteType.DETERMINISTIC_VIOLATION: "5", } @@ -175,6 +364,7 @@ class DecodedCallData(TypedDict, total=False): class GenLayerTransaction(TypedDict, total=False): """Decoded transaction data returned by get_transaction and wait_for_transaction_receipt.""" + # currentTimestamp: testnet current_timestamp: Optional[str] @@ -188,6 +378,7 @@ class GenLayerTransaction(TypedDict, total=False): # numOfInitialValidators: testnet num_of_initial_validators: Optional[str] + initial_rotations: Optional[str] # txSlot: testnet tx_slot: Optional[str] @@ -214,12 +405,17 @@ class GenLayerTransaction(TypedDict, total=False): tx_data: Optional[HexStr] tx_data_decoded: Optional[Dict[str, Any]] - # txReceipt: testnet + # The train stores only the execution hash. `tx_receipt` remains present so + # callers can distinguish unavailable legacy bytes (`None`) explicitly. + tx_execution_hash: Optional[HexStr] tx_receipt: Optional[HexStr] # messages: testnet messages: Optional[List[Any]] + # consumedValidators: testnet + consumed_validators: Optional[List[Address]] + # queueType: testnet queue_type: Optional[int] @@ -232,9 +428,9 @@ class GenLayerTransaction(TypedDict, total=False): # lastLeader: testnet last_leader: Optional[Address] - # status: localnet: TransactionStatus // status: testnet: number - status: Optional[TransactionStatus] - status_name: Optional[TransactionStatus] + # Stable consumer lifecycle. Raw protocol values are returned only by + # GenLayerClient.get_transaction_lifecycle(). + lifecycle: TransactionLifecycle # hash: localnet // txId: testnet// hash: localnet // txId: testnet hash: Optional[HexStr] @@ -297,11 +493,17 @@ class LastRound: result: int round_validators: List[Address] validator_votes_hash: List[HexStr] + validator_result_hash: List[HexStr] validator_votes: List[int] @classmethod - def from_transaction_data( - cls, tx_data: Tuple + def from_light_data( + cls, + tx_data: Tuple, + round_validators: List[Address], + validator_votes: List[int], + validator_votes_hash: List[HexStr], + validator_result_hash: List[HexStr], ) -> "GenLayerRawTransaction.LastRound": return cls( round=tx_data[0], @@ -311,29 +513,13 @@ def from_transaction_data( appeal_bond=tx_data[4], rotations_left=tx_data[5], result=tx_data[6], - round_validators=tx_data[7], - validator_votes=tx_data[8], + round_validators=round_validators, + validator_votes=validator_votes, validator_votes_hash=[ - Web3.to_hex(vote_hash) for vote_hash in tx_data[9] + Web3.to_hex(vote_hash) for vote_hash in validator_votes_hash ], - ) - - @classmethod - def from_all_data_round( - cls, tx_data: Tuple - ) -> "GenLayerRawTransaction.LastRound": - return cls( - round=tx_data[0], - leader_index=tx_data[1], - votes_committed=tx_data[2], - votes_revealed=tx_data[3], - appeal_bond=tx_data[4], - rotations_left=tx_data[5], - result=tx_data[6], - round_validators=tx_data[7], - validator_votes=tx_data[8], - validator_votes_hash=[ - Web3.to_hex(vote_hash) for vote_hash in tx_data[9] + validator_result_hash=[ + Web3.to_hex(result_hash) for result_hash in validator_result_hash ], ) @@ -348,6 +534,7 @@ def decode(self) -> Dict[str, Any]: "result": str(self.result), "round_validators": self.round_validators, "validator_votes_hash": self.validator_votes_hash, + "validator_result_hash": self.validator_result_hash, "validator_votes": self.validator_votes, "validator_votes_name": [ VOTE_TYPE_NUMBER_TO_NAME[str(vote)].value @@ -359,6 +546,7 @@ def decode(self) -> Dict[str, Any]: sender: Address recipient: Address num_of_initial_validators: int + initial_rotations: int tx_slot: int created_timestamp: int last_vote_timestamp: int @@ -366,8 +554,10 @@ def decode(self) -> Dict[str, Any]: result: int tx_execution_result: int tx_data: HexStr - tx_receipt: HexStr + tx_execution_hash: HexStr + tx_receipt: Optional[HexStr] messages: List[Any] + consumed_validators: List[Address] queue_type: int queue_position: int activator: Address @@ -379,65 +569,35 @@ def decode(self) -> Dict[str, Any]: last_round: LastRound @classmethod - def from_transaction_data(cls, tx_data: Tuple) -> "GenLayerRawTransaction": - # V06/Bradbury ABI returns 23 fields (extra txExecutionHash, eqBlocksOutputs, - # consumedValidators; txData split into txCalldata). Asimov returns 21 fields. - if len(tx_data) >= 23: - return cls._from_v06(tx_data) - return cls._from_v04(tx_data) - - @classmethod - def _from_v04(cls, tx_data: Tuple) -> "GenLayerRawTransaction": - """Asimov / pre-Bradbury ABI (21 fields).""" - return cls( - current_timestamp=tx_data[0], - sender=tx_data[1], - recipient=tx_data[2], - num_of_initial_validators=tx_data[3], - tx_slot=tx_data[4], - created_timestamp=tx_data[5], - last_vote_timestamp=tx_data[6], - random_seed=Web3.to_hex(tx_data[7]), - result=tx_data[8], - tx_execution_result=0, - tx_data=Web3.to_hex(tx_data[9]), - tx_receipt=Web3.to_hex(tx_data[10]), - messages=tx_data[11], - queue_type=tx_data[12], - queue_position=tx_data[13], - activator=tx_data[14], - last_leader=tx_data[15], - status=tx_data[16], - tx_id=Web3.to_hex(tx_data[17]), - read_state_block_range=cls.ReadStateBlockRange.from_transaction_data( - tx_data[18] - ), - num_of_rounds=tx_data[19], - last_round=cls.LastRound.from_transaction_data(tx_data[20]), - ) - - @classmethod - def _from_v06(cls, tx_data: Tuple) -> "GenLayerRawTransaction": - """Bradbury / V06 ABI (23 fields). Fields differ at positions 9-12.""" - # [9] txExecutionHash (bytes32) — not in v04 - # [10] txCalldata (bytes) — equivalent to v04's txData - # [11] eqBlocksOutputs (bytes) — not in v04 - # [12+] messages and rest shifted by +1 vs v04 - # [22] consumedValidators — not in v04 + def from_transaction_data_light( + cls, + tx_data: Tuple, + round_validators: List[Address], + validator_votes: List[int], + validator_votes_hash: List[HexStr], + validator_result_hash: List[HexStr], + consumed_validators: List[Address], + tx_execution_result: int, + num_of_initial_validators: int, + ) -> "GenLayerRawTransaction": + """Parse the bounded train transaction view and separately read arrays.""" return cls( current_timestamp=tx_data[0], sender=tx_data[1], recipient=tx_data[2], - num_of_initial_validators=tx_data[3], # initialRotations in ABI + num_of_initial_validators=num_of_initial_validators, + initial_rotations=tx_data[3], tx_slot=tx_data[4], created_timestamp=tx_data[5], last_vote_timestamp=tx_data[6], random_seed=Web3.to_hex(tx_data[7]), result=tx_data[8], - tx_execution_result=0, - tx_data=Web3.to_hex(tx_data[10]), # txCalldata - tx_receipt="0x", # not present in V06; txExecutionHash is at [9] + tx_execution_result=tx_execution_result, + tx_data=Web3.to_hex(tx_data[10]), + tx_execution_hash=Web3.to_hex(tx_data[9]), + tx_receipt=None, messages=tx_data[12], + consumed_validators=consumed_validators, queue_type=tx_data[13], queue_position=tx_data[14], activator=tx_data[15], @@ -448,72 +608,50 @@ def _from_v06(cls, tx_data: Tuple) -> "GenLayerRawTransaction": tx_data[19] ), num_of_rounds=tx_data[20], - last_round=cls.LastRound.from_transaction_data(tx_data[21]), - ) - - @classmethod - def from_all_transaction_data(cls, tx_data: Tuple, rounds_data: List[Tuple]) -> "GenLayerRawTransaction": - """Parse getTransactionAllData response which returns (transaction, roundsData[]).""" - last_round_data = rounds_data[-1] if rounds_data else None - latest_block_range = tx_data[18][-1] if tx_data[18] else (0, 0, 0) - - return cls( - current_timestamp=0, - sender=tx_data[5], - recipient=tx_data[6], - num_of_initial_validators=tx_data[9], - tx_slot=tx_data[8], - created_timestamp=0, - last_vote_timestamp=0, - random_seed=Web3.to_hex(tx_data[13]), - result=tx_data[0], - tx_execution_result=tx_data[1], - tx_data=Web3.to_hex(tx_data[16]), - tx_receipt="0x", - messages=[], - queue_type=0, - queue_position=0, - activator=tx_data[7], - last_leader=tx_data[7], - status=tx_data[3], - tx_id=Web3.to_hex(tx_data[12]), - read_state_block_range=cls.ReadStateBlockRange.from_transaction_data(latest_block_range), - num_of_rounds=len(rounds_data), - last_round=cls.LastRound.from_all_data_round(last_round_data) if last_round_data else cls.LastRound( - round=0, leader_index=0, votes_committed=0, votes_revealed=0, - appeal_bond=0, rotations_left=0, result=0, round_validators=[], - validator_votes_hash=[], validator_votes=[], + last_round=cls.LastRound.from_light_data( + tx_data[21], + round_validators, + validator_votes, + validator_votes_hash, + validator_result_hash, ), ) def decode(self) -> GenLayerTransaction: + lifecycle = transaction_lifecycle_from_protocol_status(self.status) + if lifecycle["state"] == "finalized": + outcome = transaction_outcome_from_protocol_result(self.result) + if outcome is not None: + lifecycle["outcome"] = outcome return { "current_timestamp": str(self.current_timestamp), "sender": self.sender, "recipient": self.recipient, "num_of_initial_validators": str(self.num_of_initial_validators), + "initial_rotations": str(self.initial_rotations), "tx_slot": str(self.tx_slot), "created_timestamp": str(self.created_timestamp), "last_vote_timestamp": str(self.last_vote_timestamp), "random_seed": self.random_seed, "result": str(self.result), "tx_data": self.tx_data, + "tx_execution_hash": self.tx_execution_hash, "tx_receipt": self.tx_receipt, "consensus_data": { "leader_receipt": self._decode_leader_receipt(), }, "messages": self.messages, + "consumed_validators": self.consumed_validators, "queue_type": str(self.queue_type), "queue_position": str(self.queue_position), "activator": self.activator, "last_leader": self.last_leader, - "status": str(self.status), + "lifecycle": lifecycle, "tx_id": self.tx_id, "read_state_block_range": self.read_state_block_range.decode(), "num_of_rounds": str(self.num_of_rounds), "last_round": self.last_round.decode(), "tx_data_decoded": self._decode_input_data(), - "status_name": TRANSACTION_STATUS_NUMBER_TO_NAME[str(self.status)].value, "result_name": TRANSACTION_RESULT_NUMBER_TO_NAME[str(self.result)].value, "tx_execution_result": self.tx_execution_result, "tx_execution_result_name": EXECUTION_RESULT_NUMBER_TO_NAME.get( @@ -578,7 +716,7 @@ def _decode_pending_transactions( ), "value": int.from_bytes(pending_transaction[2], byteorder="big"), "on": ( - "accepted" + "decided" if int.from_bytes(pending_transaction[3], byteorder="big") == 0 else "finalized" ), diff --git a/genlayer_py/vesting/__init__.py b/genlayer_py/vesting/__init__.py new file mode 100644 index 0000000..ad7d320 --- /dev/null +++ b/genlayer_py/vesting/__init__.py @@ -0,0 +1,51 @@ +from genlayer_py.vesting.actions import ( + vesting_delegator_join, + vesting_delegator_exit, + vesting_delegator_claim, + vesting_validator_join, + vesting_validator_deposit, + vesting_validator_exit, + vesting_validator_claim, + vesting_validator_initiate_operator_transfer, + vesting_validator_complete_operator_transfer, + vesting_validator_cancel_operator_transfer, + vesting_validator_set_identity, + vesting_withdraw, + vested_amount, + unvested_amount, + withdrawable_amount, + get_vesting_schedule, + get_vesting_state, + get_vesting_stake_info, + get_validator_wallets, + validator_wallet_count, + validator_deposited, + is_validator_wallet, + get_vesting_contract, +) + +__all__ = [ + "vesting_delegator_join", + "vesting_delegator_exit", + "vesting_delegator_claim", + "vesting_validator_join", + "vesting_validator_deposit", + "vesting_validator_exit", + "vesting_validator_claim", + "vesting_validator_initiate_operator_transfer", + "vesting_validator_complete_operator_transfer", + "vesting_validator_cancel_operator_transfer", + "vesting_validator_set_identity", + "vesting_withdraw", + "vested_amount", + "unvested_amount", + "withdrawable_amount", + "get_vesting_schedule", + "get_vesting_state", + "get_vesting_stake_info", + "get_validator_wallets", + "validator_wallet_count", + "validator_deposited", + "is_validator_wallet", + "get_vesting_contract", +] diff --git a/genlayer_py/vesting/abi/__init__.py b/genlayer_py/vesting/abi/__init__.py new file mode 100644 index 0000000..34c0257 --- /dev/null +++ b/genlayer_py/vesting/abi/__init__.py @@ -0,0 +1,9 @@ +import json +import importlib.resources + +with importlib.resources.as_file( + importlib.resources.files("genlayer_py.vesting.abi").joinpath("vesting_abi.json") +) as path, open(path, "r", encoding="utf-8") as f: + VESTING_ABI = json.load(f) + +__all__ = ["VESTING_ABI"] diff --git a/genlayer_py/vesting/abi/vesting_abi.json b/genlayer_py/vesting/abi/vesting_abi.json new file mode 100644 index 0000000..4ea485e --- /dev/null +++ b/genlayer_py/vesting/abi/vesting_abi.json @@ -0,0 +1,925 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "DelegatorJoined", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "DelegatorExited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "returned", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "int256", + "name": "rewardOrLoss", + "type": "int256" + } + ], + "name": "DelegatorClaimed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "wallet", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ValidatorJoined", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "wallet", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ValidatorDeposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "wallet", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "ValidatorExited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "wallet", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "returned", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "int256", + "name": "rewardOrLoss", + "type": "int256" + } + ], + "name": "ValidatorClaimed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "vestingContract", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum IVesting.Category", + "name": "category", + "type": "uint8" + } + ], + "name": "VestingCreated", + "type": "event" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "category", + "outputs": [ + { + "internalType": "enum IVesting.Category", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "beneficiary", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "creator", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "revoker", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "startDate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "cliffDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "periodDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "numberOfPeriods", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "cliffUnlockBps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "needsManualUnlock", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "manualUnlocked", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "revoked", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vestingStopped", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalWithdrawn", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vestedAtRevocation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalAmountAtRevocation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "revokedAt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vestingStoppedAt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vestedAtStop", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "accumulatedRewards", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "accumulatedLosses", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vestedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unvestedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawableAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "depositedPerValidator", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "pendingExitDeposited", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "validatorWallets", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "wallet", + "type": "address" + } + ], + "name": "isValidatorWallet", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "wallet", + "type": "address" + } + ], + "name": "validatorDeposited", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getValidatorWallets", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "validatorWalletCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "vestingWithdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "vestingDelegatorJoin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "vestingDelegatorExit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "vestingDelegatorClaim", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "vestingValidatorJoin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "wallet", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "vestingValidatorDeposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "wallet", + "type": "address" + }, + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "vestingValidatorExit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "wallet", + "type": "address" + } + ], + "name": "vestingValidatorClaim", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "wallet", + "type": "address" + }, + { + "internalType": "address", + "name": "newOperator", + "type": "address" + } + ], + "name": "vestingValidatorInitiateOperatorTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "wallet", + "type": "address" + } + ], + "name": "vestingValidatorCompleteOperatorTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "wallet", + "type": "address" + } + ], + "name": "vestingValidatorCancelOperatorTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "wallet", + "type": "address" + }, + { + "internalType": "string", + "name": "moniker", + "type": "string" + }, + { + "internalType": "string", + "name": "logoUri", + "type": "string" + }, + { + "internalType": "string", + "name": "website", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + }, + { + "internalType": "string", + "name": "email", + "type": "string" + }, + { + "internalType": "string", + "name": "twitter", + "type": "string" + }, + { + "internalType": "string", + "name": "telegram", + "type": "string" + }, + { + "internalType": "string", + "name": "github", + "type": "string" + }, + { + "internalType": "bytes", + "name": "extraCid", + "type": "bytes" + } + ], + "name": "vestingValidatorSetIdentity", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_beneficiary", + "type": "address" + } + ], + "name": "getVesting", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/genlayer_py/vesting/actions.py b/genlayer_py/vesting/actions.py new file mode 100644 index 0000000..26bcfc8 --- /dev/null +++ b/genlayer_py/vesting/actions.py @@ -0,0 +1,479 @@ +"""Vesting actions for GenLayerClient. + +Mirrors the genlayer_py.staking actions module. Beneficiary write +methods operate on a per-beneficiary Vesting contract address. Factory +discovery methods operate on a VestingFactory contract address. +""" + +from __future__ import annotations + +from typing import TYPE_CHECKING, List, Optional, Union + +from eth_account.signers.local import LocalAccount +from eth_typing import Address, ChecksumAddress +from hexbytes import HexBytes + +from genlayer_py.exceptions import GenLayerError +from genlayer_py.vesting.abi import VESTING_ABI + +if TYPE_CHECKING: + from genlayer_py.client import GenLayerClient + + +AddressLike = Union[Address, ChecksumAddress, str] +ExtraCidLike = Union[str, bytes, bytearray, HexBytes] + + +def _vesting_address( + self: "GenLayerClient", vesting_contract_address: AddressLike +) -> ChecksumAddress: + return self.w3.to_checksum_address(vesting_contract_address) + + +def _vesting(self: "GenLayerClient", vesting_contract_address: AddressLike): + return self.w3.eth.contract( + address=_vesting_address(self, vesting_contract_address), abi=VESTING_ABI + ) + + +def _vesting_factory(self: "GenLayerClient", vesting_factory_address: AddressLike): + return self.w3.eth.contract( + address=self.w3.to_checksum_address(vesting_factory_address), + abi=VESTING_ABI, + ) + + +def _extra_cid(extra_cid: Optional[ExtraCidLike]) -> bytes: + if not extra_cid: + return b"" + if isinstance(extra_cid, str): + if extra_cid.startswith("0x"): + return bytes(HexBytes(extra_cid)) + return extra_cid.encode() + return bytes(extra_cid) + + +def _sender( + self: "GenLayerClient", account: Optional[LocalAccount] +) -> LocalAccount: + acct = account or self.local_account + if acct is None: + raise GenLayerError("No account provided and client has no local_account") + return acct + + +def _send( + self: "GenLayerClient", + account: LocalAccount, + tx: dict, +) -> HexBytes: + """Sign and broadcast a prepared transaction dict.""" + signed = account.sign_transaction(tx) + return self.w3.eth.send_raw_transaction(signed.raw_transaction) + + +def _build( + self: "GenLayerClient", + account: LocalAccount, + to: ChecksumAddress, + data: bytes, + value: int = 0, + gas: Optional[int] = None, +) -> dict: + tx = { + "from": account.address, + "to": to, + "data": data, + "value": value, + "nonce": self.w3.eth.get_transaction_count(account.address), + "chainId": self.chain.id, + } + # Lean on the node's eth_estimateGas unless caller overrode it. + tx["gas"] = gas if gas is not None else self.w3.eth.estimate_gas(tx) * 2 + tx["gasPrice"] = self.w3.eth.gas_price + return tx + + +# --- read methods ----------------------------------------------------- + + +def vested_amount( + self: "GenLayerClient", vesting_contract_address: AddressLike +) -> int: + return _vesting(self, vesting_contract_address).functions.vestedAmount().call() + + +def unvested_amount( + self: "GenLayerClient", vesting_contract_address: AddressLike +) -> int: + return _vesting(self, vesting_contract_address).functions.unvestedAmount().call() + + +def withdrawable_amount( + self: "GenLayerClient", vesting_contract_address: AddressLike +) -> int: + return ( + _vesting(self, vesting_contract_address) + .functions.withdrawableAmount() + .call() + ) + + +def get_vesting_schedule( + self: "GenLayerClient", vesting_contract_address: AddressLike +) -> dict: + contract = _vesting(self, vesting_contract_address) + return { + "name": contract.functions.name().call(), + "category": contract.functions.category().call(), + "beneficiary": contract.functions.beneficiary().call(), + "creator": contract.functions.creator().call(), + "revoker": contract.functions.revoker().call(), + "factory": contract.functions.factory().call(), + "total_amount": contract.functions.totalAmount().call(), + "start_date": contract.functions.startDate().call(), + "cliff_duration": contract.functions.cliffDuration().call(), + "period_duration": contract.functions.periodDuration().call(), + "number_of_periods": contract.functions.numberOfPeriods().call(), + "cliff_unlock_bps": contract.functions.cliffUnlockBps().call(), + "needs_manual_unlock": contract.functions.needsManualUnlock().call(), + } + + +def get_vesting_state( + self: "GenLayerClient", vesting_contract_address: AddressLike +) -> dict: + contract = _vesting(self, vesting_contract_address) + return { + "manual_unlocked": contract.functions.manualUnlocked().call(), + "revoked": contract.functions.revoked().call(), + "vesting_stopped": contract.functions.vestingStopped().call(), + "total_withdrawn": contract.functions.totalWithdrawn().call(), + "vested_at_revocation": contract.functions.vestedAtRevocation().call(), + "total_amount_at_revocation": contract.functions.totalAmountAtRevocation() + .call(), + "revoked_at": contract.functions.revokedAt().call(), + "vesting_stopped_at": contract.functions.vestingStoppedAt().call(), + "vested_at_stop": contract.functions.vestedAtStop().call(), + "accumulated_rewards": contract.functions.accumulatedRewards().call(), + "accumulated_losses": contract.functions.accumulatedLosses().call(), + "vested_amount": contract.functions.vestedAmount().call(), + "unvested_amount": contract.functions.unvestedAmount().call(), + "withdrawable_amount": contract.functions.withdrawableAmount().call(), + } + + +def get_vesting_stake_info( + self: "GenLayerClient", + vesting_contract_address: AddressLike, + validator: AddressLike, +) -> dict: + contract = _vesting(self, vesting_contract_address) + validator_address = self.w3.to_checksum_address(validator) + return { + "deposited": contract.functions.depositedPerValidator( + validator_address + ).call(), + "pending_exit_deposited": contract.functions.pendingExitDeposited( + validator_address + ).call(), + } + + +def get_validator_wallets( + self: "GenLayerClient", vesting_contract_address: AddressLike +) -> List[ChecksumAddress]: + return ( + _vesting(self, vesting_contract_address) + .functions.getValidatorWallets() + .call() + ) + + +def validator_wallet_count( + self: "GenLayerClient", vesting_contract_address: AddressLike +) -> int: + return ( + _vesting(self, vesting_contract_address) + .functions.validatorWalletCount() + .call() + ) + + +def validator_deposited( + self: "GenLayerClient", + vesting_contract_address: AddressLike, + wallet: AddressLike, +) -> int: + return ( + _vesting(self, vesting_contract_address) + .functions.validatorDeposited(self.w3.to_checksum_address(wallet)) + .call() + ) + + +def is_validator_wallet( + self: "GenLayerClient", + vesting_contract_address: AddressLike, + wallet: AddressLike, +) -> bool: + return ( + _vesting(self, vesting_contract_address) + .functions.isValidatorWallet(self.w3.to_checksum_address(wallet)) + .call() + ) + + +def get_vesting_contract( + self: "GenLayerClient", + vesting_factory_address: AddressLike, + beneficiary: AddressLike, +) -> ChecksumAddress: + contract = _vesting_factory(self, vesting_factory_address) + vesting_contract_address = contract.functions.getVesting( + self.w3.to_checksum_address(beneficiary) + ).call() + return self.w3.to_checksum_address(vesting_contract_address) + + +# --- write methods ---------------------------------------------------- + + +def vesting_delegator_join( + self: "GenLayerClient", + vesting_contract_address: AddressLike, + validator: AddressLike, + amount: int, + account: Optional[LocalAccount] = None, +) -> HexBytes: + """Delegates `amount` GEN from a Vesting contract to a validator.""" + sender = _sender(self, account) + contract = _vesting(self, vesting_contract_address) + data = contract.encode_abi( + "vestingDelegatorJoin", + args=[self.w3.to_checksum_address(validator), amount], + ) + vesting_address = _vesting_address(self, vesting_contract_address) + tx = _build(self, sender, vesting_address, data) + return _send(self, sender, tx) + + +def vesting_delegator_exit( + self: "GenLayerClient", + vesting_contract_address: AddressLike, + validator: AddressLike, + shares: int, + account: Optional[LocalAccount] = None, +) -> HexBytes: + """Burns `shares` of a Vesting contract's delegation position.""" + sender = _sender(self, account) + contract = _vesting(self, vesting_contract_address) + data = contract.encode_abi( + "vestingDelegatorExit", + args=[self.w3.to_checksum_address(validator), shares], + ) + vesting_address = _vesting_address(self, vesting_contract_address) + tx = _build(self, sender, vesting_address, data) + return _send(self, sender, tx) + + +def vesting_delegator_claim( + self: "GenLayerClient", + vesting_contract_address: AddressLike, + validator: AddressLike, + account: Optional[LocalAccount] = None, +) -> HexBytes: + """Claims exited staking funds back into the Vesting contract.""" + sender = _sender(self, account) + contract = _vesting(self, vesting_contract_address) + data = contract.encode_abi( + "vestingDelegatorClaim", args=[self.w3.to_checksum_address(validator)] + ) + vesting_address = _vesting_address(self, vesting_contract_address) + tx = _build(self, sender, vesting_address, data) + return _send(self, sender, tx) + + +def vesting_validator_join( + self: "GenLayerClient", + vesting_contract_address: AddressLike, + operator: AddressLike, + amount: int, + account: Optional[LocalAccount] = None, +) -> HexBytes: + """Creates a validator wallet using GEN from a Vesting contract.""" + sender = _sender(self, account) + contract = _vesting(self, vesting_contract_address) + data = contract.encode_abi( + "vestingValidatorJoin", + args=[self.w3.to_checksum_address(operator), amount], + ) + vesting_address = _vesting_address(self, vesting_contract_address) + tx = _build(self, sender, vesting_address, data) + return _send(self, sender, tx) + + +def vesting_validator_deposit( + self: "GenLayerClient", + vesting_contract_address: AddressLike, + wallet: AddressLike, + amount: int, + account: Optional[LocalAccount] = None, +) -> HexBytes: + """Adds Vesting-held GEN to one of the Vesting validator wallets.""" + sender = _sender(self, account) + contract = _vesting(self, vesting_contract_address) + data = contract.encode_abi( + "vestingValidatorDeposit", + args=[self.w3.to_checksum_address(wallet), amount], + ) + vesting_address = _vesting_address(self, vesting_contract_address) + tx = _build(self, sender, vesting_address, data) + return _send(self, sender, tx) + + +def vesting_validator_exit( + self: "GenLayerClient", + vesting_contract_address: AddressLike, + wallet: AddressLike, + shares: int, + account: Optional[LocalAccount] = None, +) -> HexBytes: + """Burns `shares` from a Vesting-owned validator wallet.""" + sender = _sender(self, account) + contract = _vesting(self, vesting_contract_address) + data = contract.encode_abi( + "vestingValidatorExit", + args=[self.w3.to_checksum_address(wallet), shares], + ) + vesting_address = _vesting_address(self, vesting_contract_address) + tx = _build(self, sender, vesting_address, data) + return _send(self, sender, tx) + + +def vesting_validator_claim( + self: "GenLayerClient", + vesting_contract_address: AddressLike, + wallet: AddressLike, + account: Optional[LocalAccount] = None, +) -> HexBytes: + """Claims exited validator self-stake back into the Vesting contract.""" + sender = _sender(self, account) + contract = _vesting(self, vesting_contract_address) + data = contract.encode_abi( + "vestingValidatorClaim", args=[self.w3.to_checksum_address(wallet)] + ) + vesting_address = _vesting_address(self, vesting_contract_address) + tx = _build(self, sender, vesting_address, data) + return _send(self, sender, tx) + + +def vesting_validator_initiate_operator_transfer( + self: "GenLayerClient", + vesting_contract_address: AddressLike, + wallet: AddressLike, + new_operator: AddressLike, + account: Optional[LocalAccount] = None, +) -> HexBytes: + """Begins operator transfer for a Vesting-owned validator wallet.""" + sender = _sender(self, account) + contract = _vesting(self, vesting_contract_address) + data = contract.encode_abi( + "vestingValidatorInitiateOperatorTransfer", + args=[ + self.w3.to_checksum_address(wallet), + self.w3.to_checksum_address(new_operator), + ], + ) + vesting_address = _vesting_address(self, vesting_contract_address) + tx = _build(self, sender, vesting_address, data) + return _send(self, sender, tx) + + +def vesting_validator_complete_operator_transfer( + self: "GenLayerClient", + vesting_contract_address: AddressLike, + wallet: AddressLike, + account: Optional[LocalAccount] = None, +) -> HexBytes: + """Completes operator transfer for a Vesting-owned validator wallet.""" + sender = _sender(self, account) + contract = _vesting(self, vesting_contract_address) + data = contract.encode_abi( + "vestingValidatorCompleteOperatorTransfer", + args=[self.w3.to_checksum_address(wallet)], + ) + vesting_address = _vesting_address(self, vesting_contract_address) + tx = _build(self, sender, vesting_address, data) + return _send(self, sender, tx) + + +def vesting_validator_cancel_operator_transfer( + self: "GenLayerClient", + vesting_contract_address: AddressLike, + wallet: AddressLike, + account: Optional[LocalAccount] = None, +) -> HexBytes: + """Cancels operator transfer for a Vesting-owned validator wallet.""" + sender = _sender(self, account) + contract = _vesting(self, vesting_contract_address) + data = contract.encode_abi( + "vestingValidatorCancelOperatorTransfer", + args=[self.w3.to_checksum_address(wallet)], + ) + vesting_address = _vesting_address(self, vesting_contract_address) + tx = _build(self, sender, vesting_address, data) + return _send(self, sender, tx) + + +def vesting_validator_set_identity( + self: "GenLayerClient", + vesting_contract_address: AddressLike, + wallet: AddressLike, + moniker: str, + logo_uri: str, + website: str, + description: str, + email: str, + twitter: str, + telegram: str, + github: str, + extra_cid: Optional[ExtraCidLike] = None, + account: Optional[LocalAccount] = None, +) -> HexBytes: + """Sets identity metadata on a Vesting-owned validator wallet.""" + sender = _sender(self, account) + contract = _vesting(self, vesting_contract_address) + data = contract.encode_abi( + "vestingValidatorSetIdentity", + args=[ + self.w3.to_checksum_address(wallet), + moniker, + logo_uri, + website, + description, + email, + twitter, + telegram, + github, + _extra_cid(extra_cid), + ], + ) + vesting_address = _vesting_address(self, vesting_contract_address) + tx = _build(self, sender, vesting_address, data) + return _send(self, sender, tx) + + +def vesting_withdraw( + self: "GenLayerClient", + vesting_contract_address: AddressLike, + amount: int, + account: Optional[LocalAccount] = None, +) -> HexBytes: + """Withdraws vested tokens from a Vesting contract to its beneficiary.""" + sender = _sender(self, account) + contract = _vesting(self, vesting_contract_address) + data = contract.encode_abi("vestingWithdraw", args=[amount]) + vesting_address = _vesting_address(self, vesting_contract_address) + tx = _build(self, sender, vesting_address, data) + return _send(self, sender, tx) diff --git a/pyproject.toml b/pyproject.toml index c8002e3..6343772 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "genlayer-py" -version = "0.18.0" +version = "0.19.0-rc.2" description = "GenLayer Python SDK" authors = [ { name = "GenLayer" } @@ -28,7 +28,7 @@ where = ["."] exclude = ["tests*", "scripts*"] [tool.setuptools.package-data] -"genlayer_py" = ["consensus/abi/*.json", "staking/abi/*.json"] +"genlayer_py" = ["consensus/abi/*.json", "staking/abi/*.json", "vesting/abi/*.json"] [dependency-groups] dev = [ diff --git a/releaserc.toml b/releaserc.toml index 612b6e5..dac3fbb 100644 --- a/releaserc.toml +++ b/releaserc.toml @@ -1,6 +1,7 @@ [semantic_release] version_toml = ["pyproject.toml:project.version"] -assets = [] +assets = ["uv.lock"] +build_command = "uv lock" build_command_env = [] commit_message = "chore(release): {version}" commit_parser = "conventional" @@ -10,11 +11,16 @@ allow_zero_version = true no_git_verify = false tag_format = "v{version}" -[semantic_release.branches.main] -match = "main" +[semantic_release.branches.stable] +match = "^v[0-9]+\\.[0-9]+$" prerelease_token = "rc" prerelease = false +[semantic_release.branches.dev] +match = "^v[0-9]+\\.[0-9]+-dev$" +prerelease_token = "rc" +prerelease = true + [semantic_release.changelog] exclude_commit_patterns = [] mode = "update" @@ -61,4 +67,4 @@ insecure = false [semantic_release.publish] dist_glob_patterns = ["dist/*"] -upload_to_vcs_release = true \ No newline at end of file +upload_to_vcs_release = true diff --git a/scripts/generate-api-docs.py b/scripts/generate-api-docs.py index 7010529..4fa0d7d 100644 --- a/scripts/generate-api-docs.py +++ b/scripts/generate-api-docs.py @@ -14,9 +14,17 @@ def clean_readme(content): lines = content.split("\n") - lines = [l for l in lines if not re.match(r'^\[!\[.*\]\(https://(img\.shields\.io|dcbadge|badge\.fury)', l)] + lines = [ + l + for l in lines + if not re.match( + r"^\[!\[.*\]\(https://(img\.shields\.io|dcbadge|badge\.fury)", l + ) + ] content = "\n".join(lines) - content = re.sub(r'(## )\S*[\U0001F000-\U0001FFFF\u2600-\u27BF\u200d]+\s*', r'\1', content) + content = re.sub( + r"(## )\S*[\U0001F000-\U0001FFFF\u2600-\u27BF\u200d]+\s*", r"\1", content + ) return content @@ -26,7 +34,12 @@ def format_type(annotation): name = getattr(annotation, "__name__", None) if name: return name - return str(annotation).replace("typing.", "").replace("ForwardRef('", "").replace("')", "") + return ( + str(annotation) + .replace("typing.", "") + .replace("ForwardRef('", "") + .replace("')", "") + ) def generate_method_doc(name, method): @@ -63,7 +76,9 @@ def generate_method_doc(name, method): req_str = "yes" if required else "no" type_display = f"`{type_str}`" if type_str else "" default_display = default.lstrip(" = ") if default else "" - lines.append(f"| {pname} | {type_display} | {req_str} | {default_display} |") + lines.append( + f"| {pname} | {type_display} | {req_str} | {default_display} |" + ) lines.append("") if ret: @@ -86,7 +101,9 @@ def generate_enum_doc(name, enum_class): def main(): from genlayer_py.client.genlayer_client import GenLayerClient from genlayer_py.types.transactions import ( - TransactionStatus, TransactionResult, ExecutionResult, VoteType, + ExecutionResult, + TransactionResult, + VoteType, ) output_dir = os.path.join(os.path.dirname(__file__), "..", "docs", "api-references") @@ -103,11 +120,29 @@ def main(): lines.append(f"{client_doc}\n") public_methods = [ - "fund_account", "get_current_nonce", "initialize_consensus_smart_contract", - "read_contract", "write_contract", "simulate_write_contract", "deploy_contract", - "get_contract_schema", "get_contract_schema_for_code", "appeal_transaction", - "wait_for_transaction_receipt", "get_transaction", - "get_triggered_transaction_ids", "debug_trace_transaction", + "fund_account", + "get_current_nonce", + "initialize_consensus_smart_contract", + "read_contract", + "write_contract", + "simulate_write_contract", + "deploy_contract", + "get_contract_schema", + "get_contract_schema_for_code", + "appeal_transaction", + "top_up_fees", + "top_up_and_submit_appeal", + "can_appeal", + "get_appeal_quote", + "get_appeal_charge", + "get_min_appeal_bond", + "wait_for_decision", + "wait_for_finalization", + "wait_for_transaction_receipt", + "get_transaction", + "get_transaction_lifecycle", + "get_triggered_transaction_ids", + "debug_trace_transaction", ] for name in public_methods: method = getattr(GenLayerClient, name, None) @@ -117,7 +152,6 @@ def main(): # Enums lines.append("## Types and Enums\n") for name, enum_class in [ - ("TransactionStatus", TransactionStatus), ("TransactionResult", TransactionResult), ("ExecutionResult", ExecutionResult), ("VoteType", VoteType), diff --git a/scripts/release.sh b/scripts/release.sh index becd986..26fb4c1 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# Cut a release on the current stable branch. +# Cut a release on the current owning version branch. # # Bumps pyproject.toml, updates CHANGELOG.md via python-semantic-release, # commits, tags vX.Y.Z, and pushes both the branch commit and the tag. @@ -11,11 +11,13 @@ # you want to ship a release on (e.g. v0.18 for v0.18.x). # # Usage: -# scripts/release.sh # explicit semver — recommended +# scripts/release.sh # final release from vX.Y +# scripts/release.sh # release candidate from vX.Y-dev # scripts/release.sh patch # 0.18.0 → 0.18.1 # scripts/release.sh minor # 0.18.0 → 0.19.0 — refused unless --allow-major (see below) # scripts/release.sh major # 0.18.0 → 1.0.0 — refused unless --allow-major # scripts/release.sh --allow-major +# scripts/release.sh --dry-run [--allow-major] # # Semver-zero rule: while the major is 0, the MINOR is the breaking- # change boundary (per semver). 0.18 → 0.19 IS a major bump. The script @@ -23,7 +25,7 @@ # the current major is 0. Patches stay automatic-friendly. # # Pre-flight (each check refuses to proceed on failure): -# - On a v[.] branch (refuses on main / feature branches) +# - On vX.Y for a final or vX.Y-dev for a release candidate # - Working tree clean # - Local HEAD matches origin/ # - Latest CI run on HEAD is green @@ -31,14 +33,19 @@ set -euo pipefail ALLOW_MAJOR=0 -if [ "${1:-}" = "--allow-major" ]; then - ALLOW_MAJOR=1 +DRY_RUN=0 +while [[ "${1:-}" == --* ]]; do + case "$1" in + --allow-major) ALLOW_MAJOR=1 ;; + --dry-run) DRY_RUN=1 ;; + *) echo "Unknown option: $1" >&2; exit 2 ;; + esac shift -fi +done VERSION_ARG="${1:-}" if [ -z "$VERSION_ARG" ]; then - echo "Usage: $0 [--allow-major] |patch|minor|major" >&2 + echo "Usage: $0 [--dry-run] [--allow-major] ||patch|minor|major" >&2 exit 2 fi @@ -46,12 +53,12 @@ repo_root="$(git rev-parse --show-toplevel)" cd "$repo_root" branch="$(git rev-parse --abbrev-ref HEAD)" -if ! [[ "$branch" =~ ^v[0-9]+(\.[0-9]+)?(-dev)?$ ]]; then +if ! [[ "$branch" =~ ^v[0-9]+\.[0-9]+(-dev)?$ ]]; then cat >&2 </dev/null 2>&1; then - status="$(gh run list --branch "$branch" --commit "$local_sha" --limit 1 --json conclusion --jq '.[0].conclusion' 2>/dev/null || echo "")" - case "$status" in - success) ;; - "" ) - echo "Warning: no CI run found for $local_sha on $branch. Continuing anyway." >&2 - ;; - *) - echo "Latest CI on $branch@$local_sha is '$status' (not success). Refusing to release a red commit." >&2 - exit 1 - ;; - esac +if ! command -v gh >/dev/null 2>&1; then + echo "GitHub CLI is required to verify the release head's native tests." >&2 + exit 1 fi +status="$(gh run list --workflow tests.yml --branch "$branch" --commit "$local_sha" --limit 1 --json conclusion --jq '.[0].conclusion' 2>/dev/null || echo "")" +case "$status" in + success) ;; + "" ) + echo "No Tests workflow run found for $local_sha on $branch. Refusing to release an unverified head." >&2 + exit 1 + ;; + *) + echo "Latest Tests workflow on $branch@$local_sha is '$status' (not success). Refusing to release a red commit." >&2 + exit 1 + ;; +esac -current_version="$(grep -E '^version = ' pyproject.toml | head -1 | sed -E 's/version = "([^"]+)"/\1/')" - -# Resolve to a concrete X.Y.Z so the major-bump guard can compare. +release_flags=() case "$VERSION_ARG" in major|minor|patch) - next_version="$(python3 - "$current_version" "$VERSION_ARG" <<'PY' -import sys -cur = sys.argv[1].split(".") -kind = sys.argv[2] -major, minor, patch = int(cur[0]), int(cur[1]), int(cur[2]) -if kind == "major": - print(f"{major+1}.0.0") -elif kind == "minor": - print(f"{major}.{minor+1}.0") -elif kind == "patch": - print(f"{major}.{minor}.{patch+1}") -PY -)" + release_flags+=("--$VERSION_ARG") ;; *) - next_version="$VERSION_ARG" + requested_version="$(python3 scripts/release_version.py normalize "$VERSION_ARG")" || exit 2 ;; esac -if ! [[ "$next_version" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then - echo "Not a valid semver: $next_version" >&2 - exit 2 +if [[ "$branch" == *-dev ]]; then + release_flags+=(--as-prerelease --prerelease-token rc) fi -cur_major="${current_version%%.*}" +computed_raw="$( + uvx --from 'python-semantic-release==10.0.2' \ + semantic-release -c releaserc.toml version --print "${release_flags[@]}" +)" +next_version="$(python3 scripts/release_version.py normalize "$computed_raw")" || exit 2 + +if [[ -n "${requested_version:-}" && "$requested_version" != "$next_version" ]]; then + cat >&2 </dev/null + +last_tag="$(git describe --tags --abbrev=0 --match 'v*.*.*' 2>/dev/null || true)" +if [[ -z "$last_tag" ]]; then + echo "No previous release tag is reachable from $branch; refusing to infer release boundaries." >&2 + exit 1 +fi +last_version="$(python3 scripts/release_version.py normalize "$last_tag")" || exit 2 +cur_major="${last_version%%.*}" next_major="${next_version%%.*}" -cur_minor="$(echo "$current_version" | cut -d. -f2)" +cur_minor="$(echo "$last_version" | cut -d. -f2)" next_minor="$(echo "$next_version" | cut -d. -f2)" # Semver-zero: while major == 0, MINOR bumps are major bumps. @@ -130,7 +147,7 @@ if [ "$cur_major" = "0" ]; then if [ "$next_major" != "0" ] || [ "$next_minor" != "$cur_minor" ]; then if [ "$ALLOW_MAJOR" -ne 1 ]; then cat >&2 <&2 </dev/null +if ! git rev-parse --verify --quiet "refs/tags/v$next_version" >/dev/null; then + echo "Release tool did not create the expected tag v$next_version; refusing to push." >&2 + exit 1 +fi + # semantic-release commits and tags locally; we push explicitly so the # behaviour matches the JS-side script and the order of operations is # obvious from this file. diff --git a/scripts/release_version.py b/scripts/release_version.py new file mode 100644 index 0000000..08b4280 --- /dev/null +++ b/scripts/release_version.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python3 +"""Validate GenLayer Python release versions and their owning branches.""" + +from __future__ import annotations + +from dataclasses import dataclass +import re +import sys + + +_VERSION_PATTERN = re.compile( + r"^v?(?P0|[1-9][0-9]*)\." + r"(?P0|[1-9][0-9]*)\." + r"(?P0|[1-9][0-9]*)" + r"(?:(?:-?rc\.?(?P[1-9][0-9]*)))?$", + re.IGNORECASE, +) +_BRANCH_PATTERN = re.compile( + r"^v(?P0|[1-9][0-9]*)\." + r"(?P0|[1-9][0-9]*)(?P-dev)?$" +) + + +@dataclass(frozen=True) +class ReleaseVersion: + major: int + minor: int + patch: int + rc: int | None = None + + @property + def normalized(self) -> str: + suffix = "" if self.rc is None else f"-rc.{self.rc}" + return f"{self.major}.{self.minor}.{self.patch}{suffix}" + + @property + def is_prerelease(self) -> bool: + return self.rc is not None + + @property + def release_branch(self) -> str: + suffix = "-dev" if self.is_prerelease else "" + return f"v{self.major}.{self.minor}{suffix}" + + +def parse_release_version(value: str) -> ReleaseVersion: + match = _VERSION_PATTERN.fullmatch(value.strip()) + if match is None: + raise ValueError( + f"{value!r} is not a supported release version; use X.Y.Z for a " + "final release or X.Y.Z-rc.N for a release candidate" + ) + return ReleaseVersion( + major=int(match.group("major")), + minor=int(match.group("minor")), + patch=int(match.group("patch")), + rc=int(match.group("rc")) if match.group("rc") is not None else None, + ) + + +def validate_branch_version(branch: str, value: str) -> ReleaseVersion: + branch_match = _BRANCH_PATTERN.fullmatch(branch) + if branch_match is None: + raise ValueError( + f"{branch!r} is not a release branch; use vX.Y or vX.Y-dev" + ) + + version = parse_release_version(value) + branch_line = (int(branch_match.group("major")), int(branch_match.group("minor"))) + if branch_line != (version.major, version.minor): + raise ValueError( + f"{version.normalized} belongs to v{version.major}.{version.minor}, " + f"not {branch}" + ) + + branch_is_dev = branch_match.group("dev") is not None + if branch_is_dev and not version.is_prerelease: + raise ValueError(f"final release {version.normalized} must be cut from v{version.major}.{version.minor}") + if not branch_is_dev and version.is_prerelease: + raise ValueError( + f"release candidate {version.normalized} must be cut from " + f"v{version.major}.{version.minor}-dev" + ) + return version + + +def _usage() -> str: + return ( + "usage: release_version.py normalize | branch | " + "is-prerelease | validate | " + "verify-tag " + ) + + +def main(argv: list[str]) -> int: + try: + command = argv[1] + if command == "normalize" and len(argv) == 3: + print(parse_release_version(argv[2]).normalized) + elif command == "branch" and len(argv) == 3: + print(parse_release_version(argv[2]).release_branch) + elif command == "is-prerelease" and len(argv) == 3: + print("true" if parse_release_version(argv[2]).is_prerelease else "false") + elif command == "validate" and len(argv) == 4: + print(validate_branch_version(argv[2], argv[3]).normalized) + elif command == "verify-tag" and len(argv) == 4: + tag_version = parse_release_version(argv[2]) + package_version = parse_release_version(argv[3]) + if tag_version != package_version: + raise ValueError( + f"tag {tag_version.normalized} does not match package " + f"version {package_version.normalized}" + ) + print(tag_version.normalized) + else: + raise ValueError(_usage()) + except (IndexError, ValueError) as exc: + print(exc, file=sys.stderr) + return 2 + return 0 + + +if __name__ == "__main__": + raise SystemExit(main(sys.argv)) diff --git a/support/ci/ACTIVE_DEV_BRANCH b/support/ci/ACTIVE_DEV_BRANCH new file mode 100644 index 0000000..101debc --- /dev/null +++ b/support/ci/ACTIVE_DEV_BRANCH @@ -0,0 +1 @@ +v0.19-dev diff --git a/tests/e2e/contracts/football_prediction_market.py b/tests/e2e/contracts/football_prediction_market.py index 758c9ef..8e7e2af 100644 --- a/tests/e2e/contracts/football_prediction_market.py +++ b/tests/e2e/contracts/football_prediction_market.py @@ -1,12 +1,13 @@ # { "Depends": "py-genlayer:test" } -from genlayer import * +import genlayer as gl +from genlayer.types import * import json import typing -class PredictionMarket(gl.Contract): +class PredictionMarket(gl.contract.Contract): has_resolved: bool team1: str team2: str @@ -50,7 +51,7 @@ def resolve(self) -> typing.Any: team2 = self.team2 def get_match_result() -> str: - web_data = gl.get_webpage(market_resolution_url, mode="text") + web_data = gl.nondet.web.render(market_resolution_url, mode="text") print(web_data) task = f""" @@ -75,11 +76,11 @@ def get_match_result() -> str: your output must be only JSON without any formatting prefix or suffix. This result should be perfectly parsable by a JSON parser without errors. """ - result = gl.exec_prompt(task).replace("```json", "").replace("```", "") + result = gl.nondet.exec_prompt(task).replace("```json", "").replace("```", "") print(result) return json.dumps(json.loads(result), sort_keys=True) - result_json = json.loads(gl.eq_principle_strict_eq(get_match_result)) + result_json = json.loads(gl.eq_principle.strict_eq(get_match_result)) if result_json["winner"] > -1: self.has_resolved = True diff --git a/tests/e2e/contracts/intelligent_oracle.py b/tests/e2e/contracts/intelligent_oracle.py index ef49eb0..febbc20 100644 --- a/tests/e2e/contracts/intelligent_oracle.py +++ b/tests/e2e/contracts/intelligent_oracle.py @@ -4,7 +4,8 @@ from enum import Enum from datetime import datetime, timezone from urllib.parse import urlparse -from genlayer import * +import genlayer as gl +from genlayer.types import * class Status(Enum): @@ -13,15 +14,15 @@ class Status(Enum): ERROR = "Error" -class IntelligentOracle(gl.Contract): +class IntelligentOracle(gl.contract.Contract): # Declare persistent storage fields prediction_market_id: str title: str description: str - potential_outcomes: DynArray[str] - rules: DynArray[str] - data_source_domains: DynArray[str] - resolution_urls: DynArray[str] + potential_outcomes: gl.storage.DynArray[str] + rules: gl.storage.DynArray[str] + data_source_domains: gl.storage.DynArray[str] + resolution_urls: gl.storage.DynArray[str] earliest_resolution_date: str # Store as ISO format string status: str # Store as string since Enum isn't supported analysis: str # Store analysis results @@ -139,7 +140,7 @@ def resolve(self, evidence_url: str = "") -> None: for resource_url in resources_to_check: def evaluate_single_source() -> str: - resource_web_data = gl.get_webpage(resource_url, mode="text") + resource_web_data = gl.nondet.web.render(resource_url, mode="text") print(resource_web_data) task = f""" @@ -223,11 +224,11 @@ def evaluate_single_source() -> str: - **Clarity:** Make sure your reasoning is easy to understand. - **Validity:** Ensure the JSON output is properly formatted and free of errors. Do not include trailing commas. """ - result = gl.exec_prompt(task) + result = gl.nondet.exec_prompt(task) print(result) return result - result = gl.eq_principle_prompt_comparative( + result = gl.eq_principle.prompt_comparative( evaluate_single_source, principle="`outcome` field must be exactly the same. All other fields must be similar", ) @@ -305,11 +306,11 @@ def evaluate_all_sources() -> str: """ - result = gl.exec_prompt(task) + result = gl.nondet.exec_prompt(task) print(result) return result - result = gl.eq_principle_prompt_comparative( + result = gl.eq_principle.prompt_comparative( evaluate_all_sources, principle="`outcome` field must be exactly the same. All other fields must be similar", ) diff --git a/tests/e2e/contracts/intelligent_oracle_factory.py b/tests/e2e/contracts/intelligent_oracle_factory.py index 9cf5e3c..db54513 100644 --- a/tests/e2e/contracts/intelligent_oracle_factory.py +++ b/tests/e2e/contracts/intelligent_oracle_factory.py @@ -1,11 +1,12 @@ # { "Depends": "py-genlayer:test" } -from genlayer import * +import genlayer as gl +from genlayer.types import * -class Registry(gl.Contract): +class Registry(gl.contract.Contract): # Declare persistent storage fields - contract_addresses: DynArray[str] + contract_addresses: gl.storage.DynArray[str] intelligent_oracle_code: str def __init__(self, intelligent_oracle_code: str): @@ -24,7 +25,7 @@ def create_new_prediction_market( earliest_resolution_date: str, ) -> None: registered_contracts = len(self.contract_addresses) - contract_address = gl.deploy_contract( + contract_address = gl.contract.deploy( code=self.intelligent_oracle_code.encode("utf-8"), args=[ prediction_market_id, diff --git a/tests/e2e/contracts/llm_erc20.py b/tests/e2e/contracts/llm_erc20.py index dd28981..6dcdc1b 100644 --- a/tests/e2e/contracts/llm_erc20.py +++ b/tests/e2e/contracts/llm_erc20.py @@ -2,14 +2,15 @@ import json -from genlayer import * +import genlayer as gl +from genlayer.types import * -class LlmErc20(gl.Contract): - balances: TreeMap[Address, u256] +class LlmErc20(gl.contract.Contract): + balances: gl.storage.TreeMap[Address, u256] def __init__(self, total_supply: int) -> None: - self.balances[gl.message.sender_address] = u256(total_supply) + self.balances[gl.message.sender_address] = total_supply @gl.public.write def transfer(self, amount: int, to_address: str) -> None: @@ -47,7 +48,7 @@ def transfer(self, amount: int, to_address: str) -> None: The total sum of all balances should remain the same before and after the transaction""" final_result = ( - gl.eq_principle_prompt_non_comparative( + gl.eq_principle.prompt_non_comparative( lambda: input, task=task, criteria=criteria, diff --git a/tests/e2e/contracts/log_indexer.py b/tests/e2e/contracts/log_indexer.py index 4d5dd56..9da7df2 100644 --- a/tests/e2e/contracts/log_indexer.py +++ b/tests/e2e/contracts/log_indexer.py @@ -6,14 +6,15 @@ # } import numpy as np -from genlayer import * +import genlayer as gl +from genlayer.types import * import genlayer_embeddings as gle from dataclasses import dataclass import typing -@allow_storage +@gl.storage.allow @dataclass class StoreValue: log_id: u256 @@ -21,8 +22,10 @@ class StoreValue: # contract class -class LogIndexer(gl.Contract): - vector_store: gle.VecDB[np.float32, typing.Literal[384], StoreValue] +class LogIndexer(gl.contract.Contract): + vector_store: gle.VecDB[ + np.float32, typing.Literal[384], StoreValue, gle.EuclideanDistance + ] def __init__(self): pass @@ -52,14 +55,14 @@ def get_closest_vector(self, text: str) -> dict | None: @gl.public.write def add_log(self, log: str, log_id: int) -> None: emb = self.get_embedding(log) - self.vector_store.insert(emb, StoreValue(text=log, log_id=u256(log_id))) + self.vector_store.insert(emb, StoreValue(text=log, log_id=log_id)) @gl.public.write def update_log(self, log_id: int, log: str) -> None: emb = self.get_embedding(log) for elem in self.vector_store.knn(emb, 2): if elem.value.text == log: - elem.value.log_id = u256(log_id) + elem.value.log_id = log_id @gl.public.write def remove_log(self, id: int) -> None: diff --git a/tests/e2e/contracts/log_indexer_testnet.py b/tests/e2e/contracts/log_indexer_testnet.py index 85f396a..e0d6878 100644 --- a/tests/e2e/contracts/log_indexer_testnet.py +++ b/tests/e2e/contracts/log_indexer_testnet.py @@ -6,13 +6,14 @@ # } import numpy as np -from genlayer import * +import genlayer as gl +from genlayer.types import * import genlayermodelwrappers from dataclasses import dataclass import typing -@allow_storage +@gl.storage.allow @dataclass class StoreValue: log_id: u256 @@ -20,8 +21,8 @@ class StoreValue: # contract class -class LogIndexer(gl.Contract): - vector_store: VecDB[np.float32, typing.Literal[384], StoreValue] +class LogIndexer(gl.contract.Contract): + vector_store: genlayermodelwrappers.VecDB[np.float32, typing.Literal[384], StoreValue] def __init__(self): pass @@ -51,14 +52,14 @@ def get_closest_vector(self, text: str) -> dict | None: @gl.public.write def add_log(self, log: str, log_id: int) -> None: emb = self.get_embedding(log) - self.vector_store.insert(emb, StoreValue(text=log, log_id=u256(log_id))) + self.vector_store.insert(emb, StoreValue(text=log, log_id=log_id)) @gl.public.write def update_log(self, log_id: int, log: str) -> None: emb = self.get_embedding(log) for elem in self.vector_store.knn(emb, 2): if elem.value.text == log: - elem.value.log_id = u256(log_id) + elem.value.log_id = log_id @gl.public.write def remove_log(self, id: int) -> None: diff --git a/tests/e2e/contracts/multi_file_contract/__init__.py b/tests/e2e/contracts/multi_file_contract/__init__.py index a5258f6..f218200 100644 --- a/tests/e2e/contracts/multi_file_contract/__init__.py +++ b/tests/e2e/contracts/multi_file_contract/__init__.py @@ -1,13 +1,14 @@ -from genlayer import * +import genlayer as gl +from genlayer.types import * -class MultiFileContract(gl.Contract): +class MultiFileContract(gl.contract.Contract): other_addr: Address def __init__(self): with open("/contract/other.py", "rt") as f: text = f.read() - self.other_addr = gl.deploy_contract( + self.other_addr = gl.contract.deploy( code=text.encode("utf-8"), args=["123"], salt_nonce=1 ) @@ -17,4 +18,4 @@ def wait(self) -> None: @gl.public.view def test(self) -> str: - return gl.ContractAt(self.other_addr).view().test() + return gl.contract.get_at(self.other_addr).view().test() diff --git a/tests/e2e/contracts/multi_file_contract/other.py b/tests/e2e/contracts/multi_file_contract/other.py index 330de34..c8dc6c7 100644 --- a/tests/e2e/contracts/multi_file_contract/other.py +++ b/tests/e2e/contracts/multi_file_contract/other.py @@ -1,9 +1,10 @@ # { "Depends": "py-genlayer:test" } -from genlayer import * +import genlayer as gl +from genlayer.types import * -class Other(gl.Contract): +class Other(gl.contract.Contract): data: str def __init__(self, data: str): diff --git a/tests/e2e/contracts/multi_read_erc20.py b/tests/e2e/contracts/multi_read_erc20.py index 169d293..22d5b32 100644 --- a/tests/e2e/contracts/multi_read_erc20.py +++ b/tests/e2e/contracts/multi_read_erc20.py @@ -1,10 +1,11 @@ # { "Depends": "py-genlayer:test" } -from genlayer import * +import genlayer as gl +from genlayer.types import * -class multi_read_erc20(gl.Contract): - balances: TreeMap[Address, TreeMap[Address, u256]] +class multi_read_erc20(gl.contract.Contract): + balances: gl.storage.TreeMap[Address, gl.storage.TreeMap[Address, u256]] def __init__(self): pass @@ -14,7 +15,7 @@ def update_token_balances( self, account_address: str, token_contracts: list[str] ) -> None: for token_contract in token_contracts: - contract = gl.ContractAt(Address(token_contract)) + contract = gl.contract.get_at(Address(token_contract)) balance = contract.view().get_balance_of(account_address) self.balances.get_or_insert_default(Address(account_address))[ Address(token_contract) diff --git a/tests/e2e/contracts/multi_tenant_storage.py b/tests/e2e/contracts/multi_tenant_storage.py index 5e5af47..8659437 100644 --- a/tests/e2e/contracts/multi_tenant_storage.py +++ b/tests/e2e/contracts/multi_tenant_storage.py @@ -1,9 +1,10 @@ # { "Depends": "py-genlayer:test" } -from genlayer import * +import genlayer as gl +from genlayer.types import * -class MultiTentantStorage(gl.Contract): +class MultiTentantStorage(gl.contract.Contract): """ Same functionality as UserStorage, but implemented with multiple storage contracts. Each user is assigned to a storage contract, and all storage contracts are managed by this same contract. @@ -11,9 +12,9 @@ class MultiTentantStorage(gl.Contract): This is done to test contract calls between different contracts. """ - all_storage_contracts: DynArray[Address] - available_storage_contracts: DynArray[Address] - mappings: TreeMap[ + all_storage_contracts: gl.storage.DynArray[Address] + available_storage_contracts: gl.storage.DynArray[Address] + mappings: gl.storage.TreeMap[ Address, Address ] # mapping of user address to storage contract address @@ -29,7 +30,7 @@ def get_available_contracts(self) -> list[str]: @gl.public.view def get_all_storages(self) -> dict[str, str]: return { - storage_contract.as_hex: gl.ContractAt(storage_contract) + storage_contract.as_hex: gl.contract.get_at(storage_contract) .view() .get_storage() for storage_contract in self.all_storage_contracts @@ -45,4 +46,4 @@ def update_storage(self, new_storage: str) -> None: self.available_storage_contracts.pop() contract_to_use = self.mappings[gl.message.sender_address] - gl.ContractAt(contract_to_use).emit(gas=100000).update_storage(new_storage) + gl.contract.get_at(contract_to_use).emit().update_storage(new_storage) diff --git a/tests/e2e/contracts/read_erc20.py b/tests/e2e/contracts/read_erc20.py index 9f2d549..3883c5f 100644 --- a/tests/e2e/contracts/read_erc20.py +++ b/tests/e2e/contracts/read_erc20.py @@ -1,9 +1,10 @@ # { "Depends": "py-genlayer:test" } -from genlayer import * +import genlayer as gl +from genlayer.types import * -class read_erc20(gl.Contract): +class read_erc20(gl.contract.Contract): token_contract: Address def __init__(self, token_contract: str): @@ -11,4 +12,4 @@ def __init__(self, token_contract: str): @gl.public.view def get_balance_of(self, account_address: str) -> int: - return gl.ContractAt(self.token_contract).view().get_balance_of(account_address) + return gl.contract.get_at(self.token_contract).view().get_balance_of(account_address) diff --git a/tests/e2e/contracts/simple_time_contract.py b/tests/e2e/contracts/simple_time_contract.py index 05bfbc0..3934130 100644 --- a/tests/e2e/contracts/simple_time_contract.py +++ b/tests/e2e/contracts/simple_time_contract.py @@ -1,15 +1,16 @@ # { # "Seq": [ -# { "Depends": "py-lib-genlayer-embeddings:09h0i209wrzh4xzq86f79c60x0ifs7xcjwl53ysrnw06i54ddxyi" }, -# { "Depends": "py-genlayer:1j12s63yfjpva9ik2xgnffgrs6v44y1f52jvj9w7xvdn7qckd379" } +# { "Depends": "py-lib-genlayer-embeddings:hqpree1t3470fnac2aeee1y5c2205k22bgk1p98sg8m3s1ndmxbg" }, +# { "Depends": "py-genlayer:5jycge4q8k23462jtb0b9fyey1s9qz928sz2nbrd9mg4sxqg2qng" } # ] # } from datetime import datetime, timezone -from genlayer import * +import genlayer as gl +from genlayer.types import * -class SimpleTimeContract(gl.Contract): +class SimpleTimeContract(gl.contract.Contract): """ A simple contract that demonstrates time-based function availability. """ diff --git a/tests/e2e/contracts/storage.py b/tests/e2e/contracts/storage.py index 6cc44a9..58ff12a 100644 --- a/tests/e2e/contracts/storage.py +++ b/tests/e2e/contracts/storage.py @@ -1,10 +1,11 @@ # { "Depends": "py-genlayer:test" } -from genlayer import * +import genlayer as gl +from genlayer.types import * # contract class -class Storage(gl.Contract): +class Storage(gl.contract.Contract): storage: str # constructor diff --git a/tests/e2e/contracts/user_storage.py b/tests/e2e/contracts/user_storage.py index 3ca9fd8..3432396 100644 --- a/tests/e2e/contracts/user_storage.py +++ b/tests/e2e/contracts/user_storage.py @@ -1,10 +1,11 @@ # { "Depends": "py-genlayer:test" } -from genlayer import * +import genlayer as gl +from genlayer.types import * -class UserStorage(gl.Contract): - storage: TreeMap[Address, str] +class UserStorage(gl.contract.Contract): + storage: gl.storage.TreeMap[Address, str] # constructor def __init__(self): diff --git a/tests/e2e/contracts/wizard_of_coin.py b/tests/e2e/contracts/wizard_of_coin.py index 6194818..bff7e3f 100644 --- a/tests/e2e/contracts/wizard_of_coin.py +++ b/tests/e2e/contracts/wizard_of_coin.py @@ -1,10 +1,11 @@ # { "Depends": "py-genlayer:test" } -from genlayer import * +import genlayer as gl +from genlayer.types import * import json -class WizardOfCoin(gl.Contract): +class WizardOfCoin(gl.contract.Contract): have_coin: bool def __init__(self, have_coin: bool): @@ -39,12 +40,12 @@ def ask_for_coin(self, request: str) -> None: """ def get_wizard_answer(): - result = gl.exec_prompt(prompt) + result = gl.nondet.exec_prompt(prompt) result = result.replace("```json", "").replace("```", "") print(result) return result - result = gl.eq_principle_prompt_comparative( + result = gl.eq_principle.prompt_comparative( get_wizard_answer, "The value of give_coin has to match" ) parsed_result = json.loads(result) diff --git a/tests/e2e/tests/test_custom_validators.py b/tests/e2e/tests/test_custom_validators.py index 3754a37..6641c2d 100644 --- a/tests/e2e/tests/test_custom_validators.py +++ b/tests/e2e/tests/test_custom_validators.py @@ -2,7 +2,6 @@ from genlayer_py import create_client, create_account from genlayer_py.chains import localnet -from genlayer_py.types import TransactionStatus from genlayer_py.assertions import tx_execution_succeeded diff --git a/tests/e2e/tests/test_football_prediction_market.py b/tests/e2e/tests/test_football_prediction_market.py index f04f6ac..68200f5 100644 --- a/tests/e2e/tests/test_football_prediction_market.py +++ b/tests/e2e/tests/test_football_prediction_market.py @@ -4,7 +4,6 @@ from genlayer_py import create_client, create_account from genlayer_py.chains import localnet, studionet, testnet_asimov -from genlayer_py.types import TransactionStatus from genlayer_py.assertions import tx_execution_succeeded # Load environment variables from .env file @@ -67,7 +66,7 @@ def test_football_prediction_market(chain_config): # Wait for transaction with retries if specified wait_kwargs = { "transaction_hash": deploy_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", } if chain_config["retries"]: wait_kwargs["retries"] = chain_config["retries"] @@ -92,7 +91,7 @@ def test_football_prediction_market(chain_config): # Wait for resolve transaction with retries if specified resolve_wait_kwargs = { "transaction_hash": resolve_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", } if chain_config["retries"]: resolve_wait_kwargs["retries"] = chain_config["retries"] diff --git a/tests/e2e/tests/test_intelligent_oracle_factory.py b/tests/e2e/tests/test_intelligent_oracle_factory.py index 441cbbe..0be6c6d 100644 --- a/tests/e2e/tests/test_intelligent_oracle_factory.py +++ b/tests/e2e/tests/test_intelligent_oracle_factory.py @@ -5,7 +5,6 @@ from genlayer_py import create_client, create_account from genlayer_py.chains import localnet, studionet, testnet_asimov -from genlayer_py.types import TransactionStatus from genlayer_py.assertions import tx_execution_succeeded # Load environment variables from .env file @@ -86,7 +85,7 @@ def test_intelligent_oracle_factory_pattern(chain_config): # Wait for registry deployment registry_wait_kwargs = { "transaction_hash": registry_deploy_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", "retries": 80, } @@ -150,7 +149,7 @@ def test_intelligent_oracle_factory_pattern(chain_config): # Wait for create_new_prediction_market transaction create_wait_kwargs = { "transaction_hash": create_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", "retries": 80, } @@ -211,7 +210,7 @@ def test_intelligent_oracle_factory_pattern(chain_config): # Wait for resolve transaction resolve_wait_kwargs = { "transaction_hash": resolve_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", "retries": 80, } diff --git a/tests/e2e/tests/test_llm_erc20.py b/tests/e2e/tests/test_llm_erc20.py index 31b737d..d5598ac 100644 --- a/tests/e2e/tests/test_llm_erc20.py +++ b/tests/e2e/tests/test_llm_erc20.py @@ -4,7 +4,6 @@ from genlayer_py import create_client, create_account from genlayer_py.chains import localnet, studionet, testnet_asimov -from genlayer_py.types import TransactionStatus from genlayer_py.assertions import tx_execution_succeeded # Load environment variables from .env file @@ -79,7 +78,7 @@ def test_llm_erc20_interaction(chain_config): # Wait for transaction with retries if specified wait_kwargs = { "transaction_hash": deploy_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", } if chain_config["retries"]: wait_kwargs["retries"] = chain_config["retries"] @@ -111,7 +110,7 @@ def test_llm_erc20_interaction(chain_config): # Wait for transfer transaction with retries if specified transfer_wait_kwargs = { "transaction_hash": transfer_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", } if chain_config["retries"]: transfer_wait_kwargs["retries"] = chain_config["retries"] diff --git a/tests/e2e/tests/test_log_indexer.py b/tests/e2e/tests/test_log_indexer.py index 8510202..9dae1ff 100644 --- a/tests/e2e/tests/test_log_indexer.py +++ b/tests/e2e/tests/test_log_indexer.py @@ -4,7 +4,6 @@ from genlayer_py import create_client, create_account from genlayer_py.chains import localnet, studionet, testnet_asimov -from genlayer_py.types import TransactionStatus from genlayer_py.assertions import tx_execution_succeeded # Load environment variables from .env file @@ -69,7 +68,7 @@ def test_log_indexer(chain_config): # Wait for transaction with retries if specified wait_kwargs = { "transaction_hash": deploy_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", } if chain_config["retries"]: wait_kwargs["retries"] = chain_config["retries"] @@ -102,7 +101,7 @@ def test_log_indexer(chain_config): # Wait for add_log transaction add_log_0_wait_kwargs = { "transaction_hash": add_log_0_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", } if chain_config["retries"]: add_log_0_wait_kwargs["retries"] = chain_config["retries"] @@ -130,7 +129,7 @@ def test_log_indexer(chain_config): # Wait for add_log transaction add_log_1_wait_kwargs = { "transaction_hash": add_log_1_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", } if chain_config["retries"]: add_log_1_wait_kwargs["retries"] = chain_config["retries"] @@ -157,7 +156,7 @@ def test_log_indexer(chain_config): # Wait for update_log transaction update_log_0_wait_kwargs = { "transaction_hash": update_log_0_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", } if chain_config["retries"]: update_log_0_wait_kwargs["retries"] = chain_config["retries"] @@ -187,7 +186,7 @@ def test_log_indexer(chain_config): # Wait for remove_log transaction remove_log_0_wait_kwargs = { "transaction_hash": remove_log_0_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", } if chain_config["retries"]: remove_log_0_wait_kwargs["retries"] = chain_config["retries"] @@ -216,7 +215,7 @@ def test_log_indexer(chain_config): # Wait for add_log transaction add_log_2_wait_kwargs = { "transaction_hash": add_log_2_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", } if chain_config["retries"]: add_log_2_wait_kwargs["retries"] = chain_config["retries"] diff --git a/tests/e2e/tests/test_multi_file_contract.py b/tests/e2e/tests/test_multi_file_contract.py index f060703..3c34074 100644 --- a/tests/e2e/tests/test_multi_file_contract.py +++ b/tests/e2e/tests/test_multi_file_contract.py @@ -7,7 +7,6 @@ from genlayer_py import create_client, create_account from genlayer_py.chains import localnet, studionet, testnet_asimov -from genlayer_py.types import TransactionStatus from genlayer_py.assertions import tx_execution_succeeded # Load environment variables from .env file @@ -106,7 +105,7 @@ def test_multi_file_contract(chain_config): # Wait for transaction with retries if specified wait_kwargs = { "transaction_hash": deploy_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", } if chain_config["retries"]: wait_kwargs["retries"] = chain_config["retries"] @@ -130,7 +129,7 @@ def test_multi_file_contract(chain_config): # Wait for wait transaction wait_wait_kwargs = { "transaction_hash": wait_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", } if chain_config["retries"]: wait_wait_kwargs["retries"] = chain_config["retries"] diff --git a/tests/e2e/tests/test_multi_read_erc20.py b/tests/e2e/tests/test_multi_read_erc20.py index 472a245..1a3ea2c 100644 --- a/tests/e2e/tests/test_multi_read_erc20.py +++ b/tests/e2e/tests/test_multi_read_erc20.py @@ -4,7 +4,6 @@ from genlayer_py import create_client, create_account from genlayer_py.chains import localnet, studionet, testnet_asimov -from genlayer_py.types import TransactionStatus from genlayer_py.assertions import tx_execution_succeeded # Load environment variables from .env file @@ -94,7 +93,7 @@ def test_multi_read_erc20(chain_config): # Wait for doge deployment doge_wait_kwargs = { "transaction_hash": doge_deploy_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", } if chain_config["retries"]: doge_wait_kwargs["retries"] = chain_config["retries"] @@ -115,7 +114,7 @@ def test_multi_read_erc20(chain_config): # Wait for shiba deployment shiba_wait_kwargs = { "transaction_hash": shiba_deploy_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", } if chain_config["retries"]: shiba_wait_kwargs["retries"] = chain_config["retries"] @@ -138,7 +137,7 @@ def test_multi_read_erc20(chain_config): # Wait for multi-read deployment multi_read_wait_kwargs = { "transaction_hash": multi_read_deploy_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", } if chain_config["retries"]: multi_read_wait_kwargs["retries"] = chain_config["retries"] @@ -166,7 +165,7 @@ def test_multi_read_erc20(chain_config): # Wait for update_token_balances transaction update_balances_doge_wait_kwargs = { "transaction_hash": update_balances_doge_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", } if chain_config["retries"]: update_balances_doge_wait_kwargs["retries"] = chain_config["retries"] @@ -201,7 +200,7 @@ def test_multi_read_erc20(chain_config): # Wait for update_token_balances transaction update_balances_shiba_wait_kwargs = { "transaction_hash": update_balances_shiba_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", } if chain_config["retries"]: update_balances_shiba_wait_kwargs["retries"] = chain_config["retries"] diff --git a/tests/e2e/tests/test_multi_tenant_storage.py b/tests/e2e/tests/test_multi_tenant_storage.py index 0353749..18e33d8 100644 --- a/tests/e2e/tests/test_multi_tenant_storage.py +++ b/tests/e2e/tests/test_multi_tenant_storage.py @@ -4,7 +4,7 @@ from genlayer_py import create_client, create_account from genlayer_py.chains import localnet, studionet, testnet_asimov -from genlayer_py.types import TransactionStatus, GenLayerTransaction +from genlayer_py.types import GenLayerTransaction from genlayer_py.client import GenLayerClient from genlayer_py.assertions import tx_execution_succeeded @@ -24,7 +24,7 @@ def wait_for_triggered_transactions( for triggered_transaction in tx_receipt["triggered_transactions"]: client.wait_for_transaction_receipt( transaction_hash=triggered_transaction, - status=TransactionStatus.FINALIZED, + wait_until="finalized", ) @@ -110,7 +110,7 @@ def test_multi_tenant_storage(chain_config): # Wait for first storage deployment first_storage_wait_kwargs = { "transaction_hash": first_storage_deploy_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", } if chain_config["retries"]: first_storage_wait_kwargs["retries"] = chain_config["retries"] @@ -133,7 +133,7 @@ def test_multi_tenant_storage(chain_config): # Wait for second storage deployment second_storage_wait_kwargs = { "transaction_hash": second_storage_deploy_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", } if chain_config["retries"]: second_storage_wait_kwargs["retries"] = chain_config["retries"] @@ -158,7 +158,7 @@ def test_multi_tenant_storage(chain_config): # Wait for multi-tenant storage deployment multi_tenant_storage_wait_kwargs = { "transaction_hash": multi_tenant_storage_deploy_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", } if chain_config["retries"]: multi_tenant_storage_wait_kwargs["retries"] = chain_config["retries"] @@ -185,7 +185,7 @@ def test_multi_tenant_storage(chain_config): # Wait for update_storage transaction update_storage_a_wait_kwargs = { "transaction_hash": update_storage_a_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", } if chain_config["retries"]: update_storage_a_wait_kwargs["retries"] = chain_config["retries"] @@ -207,7 +207,7 @@ def test_multi_tenant_storage(chain_config): # Wait for update_storage transaction update_storage_b_wait_kwargs = { "transaction_hash": update_storage_b_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", } if chain_config["retries"]: update_storage_b_wait_kwargs["retries"] = chain_config["retries"] diff --git a/tests/e2e/tests/test_read_erc20.py b/tests/e2e/tests/test_read_erc20.py index 1b6f49c..ea6172e 100644 --- a/tests/e2e/tests/test_read_erc20.py +++ b/tests/e2e/tests/test_read_erc20.py @@ -4,7 +4,6 @@ from genlayer_py import create_client, create_account from genlayer_py.chains import localnet, studionet, testnet_asimov -from genlayer_py.types import TransactionStatus from genlayer_py.assertions import tx_execution_succeeded # Load environment variables from .env file @@ -82,7 +81,7 @@ def test_read_erc20(chain_config): # Wait for LLM ERC20 deployment llm_erc20_wait_kwargs = { "transaction_hash": llm_erc20_deploy_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", } if chain_config["retries"]: llm_erc20_wait_kwargs["retries"] = chain_config["retries"] @@ -111,7 +110,7 @@ def test_read_erc20(chain_config): # Wait for read_erc20 deployment read_erc20_wait_kwargs = { "transaction_hash": read_erc20_deploy_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", } if chain_config["retries"]: read_erc20_wait_kwargs["retries"] = chain_config["retries"] diff --git a/tests/e2e/tests/test_storage.py b/tests/e2e/tests/test_storage.py index ad108a6..7f4f15a 100644 --- a/tests/e2e/tests/test_storage.py +++ b/tests/e2e/tests/test_storage.py @@ -4,7 +4,6 @@ from genlayer_py import create_client, create_account from genlayer_py.chains import localnet, studionet, testnet_asimov -from genlayer_py.types import TransactionStatus from genlayer_py.assertions import tx_execution_succeeded # Load environment variables from .env file @@ -67,7 +66,7 @@ def test_storage_interaction(chain_config): # Wait for transaction with retries if specified wait_kwargs = { "transaction_hash": deploy_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", } if chain_config["retries"]: wait_kwargs["retries"] = chain_config["retries"] @@ -99,7 +98,7 @@ def test_storage_interaction(chain_config): # Wait for write transaction with retries if specified write_wait_kwargs = { "transaction_hash": write_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", } if chain_config["retries"]: write_wait_kwargs["retries"] = chain_config["retries"] diff --git a/tests/e2e/tests/test_user_storage.py b/tests/e2e/tests/test_user_storage.py index 5c12865..3999d10 100644 --- a/tests/e2e/tests/test_user_storage.py +++ b/tests/e2e/tests/test_user_storage.py @@ -4,7 +4,6 @@ from genlayer_py import create_client, create_account from genlayer_py.chains import localnet, studionet, testnet_asimov -from genlayer_py.types import TransactionStatus from genlayer_py.assertions import tx_execution_succeeded # Load environment variables from .env file @@ -79,7 +78,7 @@ def test_user_storage(chain_config): # Wait for transaction with retries if specified wait_kwargs = { "transaction_hash": deploy_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", } if chain_config["retries"]: wait_kwargs["retries"] = chain_config["retries"] @@ -111,7 +110,7 @@ def test_user_storage(chain_config): # Wait for update_storage transaction update_storage_a_wait_kwargs = { "transaction_hash": update_storage_a_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", } if chain_config["retries"]: update_storage_a_wait_kwargs["retries"] = chain_config["retries"] @@ -146,7 +145,7 @@ def test_user_storage(chain_config): # Wait for update_storage transaction update_storage_b_wait_kwargs = { "transaction_hash": update_storage_b_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", } if chain_config["retries"]: update_storage_b_wait_kwargs["retries"] = chain_config["retries"] @@ -174,7 +173,7 @@ def test_user_storage(chain_config): # Wait for update_storage transaction update_storage_a2_wait_kwargs = { "transaction_hash": update_storage_a2_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", } if chain_config["retries"]: update_storage_a2_wait_kwargs["retries"] = chain_config["retries"] diff --git a/tests/e2e/tests/test_wizard_of_coin.py b/tests/e2e/tests/test_wizard_of_coin.py index 8de6e8a..0d61927 100644 --- a/tests/e2e/tests/test_wizard_of_coin.py +++ b/tests/e2e/tests/test_wizard_of_coin.py @@ -4,7 +4,6 @@ from genlayer_py import create_client, create_account from genlayer_py.chains import localnet, studionet, testnet_asimov -from genlayer_py.types import TransactionStatus from genlayer_py.assertions import tx_execution_succeeded # Load environment variables from .env file @@ -65,7 +64,7 @@ def test_wizard_of_coin(chain_config): # Wait for transaction with retries if specified wait_kwargs = { "transaction_hash": deploy_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", } if chain_config["retries"]: wait_kwargs["retries"] = chain_config["retries"] @@ -90,7 +89,7 @@ def test_wizard_of_coin(chain_config): # Wait for ask_for_coin transaction ask_for_coin_wait_kwargs = { "transaction_hash": ask_for_coin_tx_hash, - "status": TransactionStatus.FINALIZED, + "wait_until": "finalized", } if chain_config["retries"]: ask_for_coin_wait_kwargs["retries"] = chain_config["retries"] diff --git a/tests/unit/account/test_accounts.py b/tests/unit/account/test_accounts.py index 4e0a22c..b3ec88c 100644 --- a/tests/unit/account/test_accounts.py +++ b/tests/unit/account/test_accounts.py @@ -1,7 +1,10 @@ from eth_account import Account from eth_account.signers.local import LocalAccount +from types import SimpleNamespace +from unittest.mock import Mock from genlayer_py.accounts.account import generate_private_key, create_account +from genlayer_py.accounts.actions import get_current_nonce def test_generate_private_key(): @@ -54,3 +57,25 @@ def test_create_account_with_none_private_key(): assert ( account1.address != account2.address ) # Different addresses since different random keys + + +def test_get_current_nonce_includes_pending_transactions_by_default(): + address = "0x0000000000000000000000000000000000000001" + client = SimpleNamespace( + account=SimpleNamespace(address=address), + get_transaction_count=Mock(return_value=7), + ) + + assert get_current_nonce(client) == 7 + client.get_transaction_count.assert_called_once_with(address, "pending") + + +def test_get_current_nonce_preserves_explicit_block_identifier(): + address = "0x0000000000000000000000000000000000000001" + client = SimpleNamespace( + account=None, + get_transaction_count=Mock(return_value=3), + ) + + assert get_current_nonce(client, address, "latest") == 3 + client.get_transaction_count.assert_called_once_with(address, "latest") diff --git a/tests/unit/chains/test_chain_actions.py b/tests/unit/chains/test_chain_actions.py index 2e9e9b8..6c07f72 100644 --- a/tests/unit/chains/test_chain_actions.py +++ b/tests/unit/chains/test_chain_actions.py @@ -5,6 +5,7 @@ from genlayer_py.chains.actions import initialize_consensus_smart_contract from genlayer_py.chains.localnet import localnet +from genlayer_py.chains.studio_devnet import studio_devnet from genlayer_py.exceptions import GenLayerError @@ -45,6 +46,22 @@ def test_initialize_consensus_refreshes_runtime_contract_for_local_chain(): assert getattr(client.chain, "__consensus_abi_fetched_from_rpc") is True +def test_initialize_consensus_refreshes_runtime_contract_for_studio_devnet(): + client = _make_client( + chain_id=studio_devnet.id, + consensus_main_contract={"address": "0x1", "abi": [{"type": "function"}]}, + ) + rpc_contract = {"address": "0x2", "abi": [{"type": "function", "name": "foo"}]} + client.provider.make_request.return_value = {"result": rpc_contract} + + initialize_consensus_smart_contract(self=client) + + client.provider.make_request.assert_called_once_with( + method="sim_getConsensusContract", params=["ConsensusMain"] + ) + assert client.chain.consensus_main_contract == rpc_contract + + def test_initialize_consensus_falls_back_to_static_contract_on_local_rpc_failure(): static_contract = {"address": "0x1", "abi": [{"type": "function"}]} client = _make_client( diff --git a/tests/unit/chains/test_chain_presets.py b/tests/unit/chains/test_chain_presets.py new file mode 100644 index 0000000..f500829 --- /dev/null +++ b/tests/unit/chains/test_chain_presets.py @@ -0,0 +1,59 @@ +import genlayer_py + +from genlayer_py.chains import __all__ as chain_exports +from genlayer_py.chains.localnet import localnet +from genlayer_py.chains.studio_devnet import ( + STUDIO_DEVNET_EXPLORER_URL, + STUDIO_DEVNET_JSON_RPC_URL, + studio_devnet, +) +from genlayer_py.chains.studionet import studionet +from genlayer_py.chains.testnet_asimov import testnet_asimov +from genlayer_py.chains.utils import is_studio_chain + + +def test_localnet_uses_the_canonical_local_studio_chain_id(): + assert localnet.id == 61127 + assert localnet.rpc_urls == { + "default": {"http": ["http://127.0.0.1:4000/api"]} + } + + +def test_studio_devnet_is_exported_with_canonical_preview_coordinates(): + assert "studio_devnet" in chain_exports + assert genlayer_py.studio_devnet is studio_devnet + assert studio_devnet.id == 61997 + assert studio_devnet.name == "GenLayer Studio Devnet" + assert studio_devnet.rpc_urls == { + "default": {"http": ["https://studio-dev.genlayer.com/api"]} + } + assert STUDIO_DEVNET_JSON_RPC_URL == "https://studio-dev.genlayer.com/api" + assert STUDIO_DEVNET_EXPLORER_URL == "https://explorer-studio-dev.genlayer.com" + assert studio_devnet.block_explorers == { + "default": { + "name": "GenLayer Explorer", + "url": "https://explorer-studio-dev.genlayer.com", + } + } + assert studio_devnet.consensus_main_contract == studionet.consensus_main_contract + assert studio_devnet.consensus_data_contract == studionet.consensus_data_contract + assert studio_devnet.consensus_main_contract is not studionet.consensus_main_contract + assert studio_devnet.consensus_data_contract is not studionet.consensus_data_contract + + +def test_stable_studionet_coordinates_do_not_drift_with_preview_preset(): + assert studionet.id == 61999 + assert studionet.rpc_urls == { + "default": {"http": ["https://studio.genlayer.com/api"]} + } + + +def test_studio_chain_classification_includes_preview_but_not_public_testnet(): + assert is_studio_chain(localnet) + assert is_studio_chain(studionet) + assert is_studio_chain(studio_devnet) + assert not is_studio_chain(testnet_asimov) + + +def test_studio_presets_have_distinct_chain_ids(): + assert len({localnet.id, studio_devnet.id, studionet.id}) == 3 diff --git a/tests/unit/conftest.py b/tests/unit/conftest.py index e182e24..1e42103 100644 --- a/tests/unit/conftest.py +++ b/tests/unit/conftest.py @@ -94,14 +94,13 @@ def sample_transaction_data(): "gaslimit": 2, "nonce": 1, "type": 2, - "status": 7, # FINALIZED - "status_name": "FINALIZED", + "lifecycle": {"state": "finalized", "outcome": "accepted"}, "result": "6", "result_name": "MAJORITY_AGREE", "created_at": "2025-07-22T19:58:39.866436+00:00", "data": { "calldata": { - "readable": '{"args":[500,"0x4C76986555e8C63bD0D9CFAFbf8e68C338556b6b"],"method":"transfer"}' + "readable": '{"":"transfer","args":[500,"0x4C76986555e8C63bD0D9CFAFbf8e68C338556b6b"]}' } }, "contract_snapshot": { @@ -115,8 +114,7 @@ def pending_transaction_data(): """Transaction in pending state""" return { "hash": "0x4b8037744adab7ea8335b4f839979d20031d83a8ccdf706e0ae61312930335f6", - "status": 1, # PENDING - "status_name": "PENDING", + "lifecycle": {"state": "processing", "phase": "pending"}, "from_address": "0xd650f318A0C1F940a3b6dFeA695747fA9804D685", "to_address": "0xf72aa51B6350C18966923073d3609e1356a3fbBA", "value": 0, @@ -128,8 +126,7 @@ def pending_transaction_data(): def accepted_transaction_data(sample_transaction_data): """Transaction in accepted state""" data = sample_transaction_data.copy() - data["status"] = 5 # ACCEPTED - data["status_name"] = "ACCEPTED" + data["lifecycle"] = {"state": "decided", "outcome": "accepted"} return data diff --git a/tests/unit/consensus/test_consensus_main.py b/tests/unit/consensus/test_consensus_main.py index dd37be8..ccaf909 100644 --- a/tests/unit/consensus/test_consensus_main.py +++ b/tests/unit/consensus/test_consensus_main.py @@ -3,6 +3,7 @@ encode_tx_data_call, encode_tx_data_deploy, ) +from genlayer_py.abi import calldata from genlayer_py.consensus.consensus_main import decode_add_transaction_data from genlayer_py.transactions import MessageType from web3 import Web3 @@ -39,7 +40,7 @@ def test_codec_add_transaction_data_1(): ) assert decoded_data["num_of_initial_validators"] == 10 assert decoded_data["max_rotations"] == 10 - assert decoded_data["tx_data"]["decoded"]["call_data"]["method"] == "addTransaction" + assert decoded_data["tx_data"]["decoded"]["call_data"][""] == "addTransaction" assert decoded_data["tx_data"]["decoded"]["leader_only"] is False assert decoded_data["tx_data"]["decoded"]["type"] == "call" @@ -73,7 +74,7 @@ def test_codec_add_transaction_data_2(): ) assert decoded_data["num_of_initial_validators"] == 5 assert decoded_data["max_rotations"] == 1 - assert decoded_data["tx_data"]["decoded"]["call_data"]["method"] == "set_store" + assert decoded_data["tx_data"]["decoded"]["call_data"][""] == "set_store" assert decoded_data["tx_data"]["decoded"]["leader_only"] is False assert decoded_data["tx_data"]["decoded"]["type"] == "call" @@ -158,4 +159,28 @@ def test_codec_fee_aware_add_transaction_data_round_trip(): assert decoded_data["fees_distribution"]["totalMessageFees"] == 11 assert decoded_data["message_allocations"][0]["messageType"] == MessageType.Internal assert decoded_data["message_allocations"][0]["onAcceptance"] is False - assert decoded_data["tx_data"]["decoded"]["call_data"]["method"] == "set_store" + assert decoded_data["tx_data"]["decoded"]["call_data"][""] == "set_store" + + +def test_method_key_is_empty_string_binary_prefix(): + tx_data = encode_tx_data_call( + function_name="my_method", + leader_only=False, + args=["value"], + kwargs={}, + ) + encoded_data = encode_add_transaction_data( + sender_address="0x3d338dea364bdac3c4c3036a38766870b98c4320", + recipient_address="0x7f3ebb777cd2ae9c266d6cea2c7a3ed81c30ddc2", + num_of_initial_validators=5, + max_rotations=1, + tx_data=tx_data.hex() if isinstance(tx_data, bytes) else tx_data, + ) + + decoded_data = decode_add_transaction_data(encoded_data) + call_data = decoded_data["tx_data"]["decoded"]["call_data"] + assert "" in call_data and call_data[""] == "my_method" + assert 'method' not in call_data + + raw = calldata.encode(call_data) + assert b"my_method" in raw and raw.index(b"my_method") < raw.index(b"args") diff --git a/tests/unit/contracts/test_contract_actions.py b/tests/unit/contracts/test_contract_actions.py index cc58d44..bc8b36a 100644 --- a/tests/unit/contracts/test_contract_actions.py +++ b/tests/unit/contracts/test_contract_actions.py @@ -2,31 +2,42 @@ from unittest.mock import Mock import eth_utils +import pytest from eth_abi import decode as abi_decode from web3 import Web3 import genlayer_py.contracts.actions as contract_actions from genlayer_py.chains import localnet +from genlayer_py.chains.studio_devnet import studio_devnet +from genlayer_py.chains.testnet_asimov import testnet_asimov +from genlayer_py.consensus.abi import CONSENSUS_MAIN_ABI +from genlayer_py.exceptions import GenLayerError from genlayer_py.transactions.fees import ( ADD_TRANSACTION_WITH_FEES_ARGUMENT_TYPES, ADD_TRANSACTION_WITH_FEES_SELECTOR, CALL_KEY_DEPLOY, CALL_KEY_UNNAMED, CALL_KEY_WILDCARD, + DEPLOY_CALL_KEY, FEES_DISTRIBUTION_ABI_TYPE, MESSAGE_ALLOCATION_ROOT_PARENT_INDEX, MessageType, build_estimated_fees_distribution, calculate_local_round_fees, create_fees_distribution, + create_top_up_fees_distribution, derive_external_message_call_key, derive_internal_message_call_key, + deploy_call_key, encode_external_message_fee_params, encode_internal_message_fee_params, extract_studio_fee_policy, requires_fee_deposit_calculation, ) +DEFAULT_PARENT_MESSAGE_RECEIPT_HEADROOM = 10_000 +LOCAL_EXECUTION_BUDGET_FLOOR_GAS = 306_192 + ADD_TRANSACTION_ABI_V5 = [ { @@ -115,6 +126,20 @@ } ] +# Studio refetches its decision-bound ConsensusMain ABI from the simulator RPC. +STUDIO_CONSENSUS_MAIN_ABI = [ + { + "type": "function", + "name": "submitAppeal", + "stateMutability": "payable", + "inputs": [ + {"name": "_txId", "type": "bytes32"}, + {"name": "_expectedDecisionId", "type": "uint256"}, + ], + "outputs": [], + }, +] + SENDER = "0x1111111111111111111111111111111111111111" RECIPIENT = "0x2222222222222222222222222222222222222222" TX_ID = "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" @@ -128,14 +153,33 @@ def test_encode_internal_message_fee_params_uses_consensus_tuple_shape(): "appealRounds": 1, "executionBudgetPerRound": 20, "rotations": [2, 3], + "maxPriceGenPerTimeUnit": 30, + "storageFeeMaxGasPrice": 40, + "receiptFeeMaxGasPrice": 50, } ) decoded = abi_decode( - ("(uint256,uint256,uint256,uint256,uint256[])",), + ("(uint256,uint256,uint256,uint256,uint256[],uint256,uint256,uint256)",), Web3.to_bytes(hexstr=encoded), )[0] - assert decoded == (5, 10, 1, 20, (2, 3)) + assert decoded == (5, 10, 1, 20, (2, 3), 30, 40, 50) + + +def test_encode_internal_message_fee_params_accepts_snake_case_price_caps(): + encoded = encode_internal_message_fee_params( + { + "max_price_gen_per_time_unit": 30, + "storage_fee_max_gas_price": 40, + "receipt_fee_max_gas_price": 50, + } + ) + + decoded = abi_decode( + ("(uint256,uint256,uint256,uint256,uint256[],uint256,uint256,uint256)",), + Web3.to_bytes(hexstr=encoded), + )[0] + assert decoded == (0, 0, 0, 0, (0,), 30, 40, 50) def test_derive_internal_message_call_key_for_short_method_name(): @@ -152,7 +196,15 @@ def test_derive_internal_message_call_key_hashes_exact_32_byte_method_name(): def test_derive_message_call_key_constants_for_deploy_and_unnamed(): - assert CALL_KEY_DEPLOY == "0x" + "00" * 32 + # Wildcard is the untagged hash of empty bytes — outside the derived-key space. + assert CALL_KEY_WILDCARD == eth_utils.keccak(b"") + assert CALL_KEY_WILDCARD == bytes.fromhex( + "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + ) + # Empty name derives bytes32(0): the natural key for deploy and emit_transfer. + assert DEPLOY_CALL_KEY == "0x" + "00" * 32 + assert CALL_KEY_DEPLOY == DEPLOY_CALL_KEY + assert deploy_call_key() == DEPLOY_CALL_KEY assert CALL_KEY_UNNAMED == "0x" + "00" * 32 assert derive_internal_message_call_key("") == CALL_KEY_UNNAMED @@ -190,12 +242,8 @@ def test_encode_top_up_fees_uses_consensus_tuple_shape(): function_name="topUpFees", transaction_id=TX_ID, distribution={ - "leaderTimeunitsAllocation": 100, - "validatorTimeunitsAllocation": 200, - "appealRounds": 1, "executionBudgetPerRound": 500_000, "totalMessageFees": 30, - "rotations": [0, 2], "maxPriceGenPerTimeUnit": 12, "storageFeeMaxGasPrice": 24, "receiptFeeMaxGasPrice": 36, @@ -211,7 +259,18 @@ def test_encode_top_up_fees_uses_consensus_tuple_shape(): Web3.to_bytes(hexstr=encoded[10:]), ) assert decoded_tx_id == Web3.to_bytes(hexstr=TX_ID) - assert distribution == (100, 200, 1, 500_000, 0, 30, (0, 2), 12, 24, 36) + assert distribution == (0, 0, 0, 500_000, 0, 30, (), 12, 24, 36) + + +def test_top_up_distribution_preserves_explicit_initial_schedule(): + assert create_top_up_fees_distribution({"appealRounds": 1, "rotations": [0, 2]})[ + "rotations" + ] == [0, 2] + + +def test_top_up_distribution_requires_schedule_for_nonzero_appeal_rounds(): + with pytest.raises(ValueError, match=r"rotations must contain appealRounds \+ 1"): + create_top_up_fees_distribution({"appealRounds": 1}) def test_top_up_fees_sends_consensus_call(monkeypatch): @@ -243,7 +302,324 @@ def fake_send_consensus_call(**kwargs): def test_top_up_and_submit_appeal_sends_consensus_call_and_returns_tx_id(monkeypatch): - client = _make_client(ADD_TRANSACTION_ABI_WITH_FEES) + client = _make_client(ADD_TRANSACTION_ABI_WITH_FEES, chain_id=testnet_asimov.id) + captured = {} + + def fake_send_consensus_call(**kwargs): + captured.update(kwargs) + return "0xevmtx" + + monkeypatch.setattr( + contract_actions, + "_send_consensus_call", + fake_send_consensus_call, + ) + + result = contract_actions.top_up_and_submit_appeal( + self=client, + transaction_id=TX_ID, + value=1234, + expected_decision_id=42, + distribution={"appealRounds": 1, "rotations": [0, 1]}, + ) + + selector = eth_utils.keccak( + text=f"topUpAndSubmitAppeal(bytes32,uint256,{FEES_DISTRIBUTION_ABI_TYPE})" + )[:4].hex() + assert result == TX_ID + assert captured["value"] == 1234 + assert captured["operation_name"] == "Top up and submit appeal" + assert captured["encoded_data"].startswith(f"0x{selector}") + decoded_tx_id, decision_id, _ = abi_decode( + ("bytes32", "uint256", FEES_DISTRIBUTION_ABI_TYPE), + Web3.to_bytes(hexstr=captured["encoded_data"][10:]), + ) + assert decoded_tx_id == Web3.to_bytes(hexstr=TX_ID) + assert decision_id == 42 + + +def test_encode_submit_appeal_uses_exact_decision_guarded_selector(): + client = _make_client(CONSENSUS_MAIN_ABI) + + encoded = contract_actions._encode_submit_appeal_data( + self=client, + transaction_id=TX_ID, + expected_decision_id=42, + ) + + selector = eth_utils.keccak(text="submitAppeal(bytes32,uint256)")[:4].hex() + assert encoded.startswith(f"0x{selector}") + assert abi_decode(("bytes32", "uint256"), Web3.to_bytes(hexstr=encoded[10:])) == ( + Web3.to_bytes(hexstr=TX_ID), + 42, + ) + + +def test_appeal_transaction_auto_resolves_latest_quote(monkeypatch): + client = _make_client(ADD_TRANSACTION_ABI_WITH_FEES, chain_id=testnet_asimov.id) + captured = {} + + monkeypatch.setattr( + contract_actions, + "get_appeal_quote", + Mock( + return_value={ + "decision_id": 42, + "bond": 4_000, + "funding": 321, + "total": 4_321, + "appeal_deadline": 999, + } + ), + ) + def fake_send_consensus_call(**kwargs): + captured.update(kwargs) + return "0xevmtx" + + monkeypatch.setattr( + contract_actions, + "_send_consensus_call", + fake_send_consensus_call, + ) + + result = contract_actions.appeal_transaction( + self=client, + transaction_id=TX_ID, + ) + + assert result == TX_ID + contract_actions.get_appeal_quote.assert_called_once_with(client, TX_ID) + selector = eth_utils.keccak( + text=f"topUpAndSubmitAppeal(bytes32,uint256,{FEES_DISTRIBUTION_ABI_TYPE})" + )[:4].hex() + assert captured["encoded_data"].startswith(f"0x{selector}") + tx_id, decision_id, distribution = abi_decode( + ("bytes32", "uint256", FEES_DISTRIBUTION_ABI_TYPE), + Web3.to_bytes(hexstr=captured["encoded_data"][10:]), + ) + assert tx_id == Web3.to_bytes(hexstr=TX_ID) + assert decision_id == 42 + assert distribution[2] == 0 + assert distribution[6] == (0,) + assert captured["value"] == 4_321 + assert captured["operation_name"] == "Appeal" + + +def test_top_up_and_submit_appeal_auto_resolves_latest_quote(monkeypatch): + client = _make_client(ADD_TRANSACTION_ABI_WITH_FEES, chain_id=testnet_asimov.id) + captured = {} + + monkeypatch.setattr( + contract_actions, + "get_appeal_quote", + Mock( + return_value={ + "decision_id": 77, + "bond": 9_000, + "funding": 999, + "total": 9_999, + "appeal_deadline": 1_234, + } + ), + ) + + def fake_send_consensus_call(**kwargs): + captured.update(kwargs) + return "0xevmtx" + + monkeypatch.setattr( + contract_actions, + "_send_consensus_call", + fake_send_consensus_call, + ) + + result = contract_actions.top_up_and_submit_appeal( + self=client, + transaction_id=TX_ID, + distribution={"appealRounds": 1, "rotations": [0, 1]}, + ) + + assert result == TX_ID + assert captured["value"] == 9_999 + _, decision_id, _ = abi_decode( + ("bytes32", "uint256", FEES_DISTRIBUTION_ABI_TYPE), + Web3.to_bytes(hexstr=captured["encoded_data"][10:]), + ) + assert decision_id == 77 + + +def test_appeal_auto_quote_failure_is_actionable(monkeypatch): + client = _make_client(ADD_TRANSACTION_ABI_WITH_FEES, chain_id=testnet_asimov.id) + monkeypatch.setattr( + contract_actions, + "get_appeal_quote", + Mock(side_effect=RuntimeError("no active decision")), + ) + + with pytest.raises(GenLayerError, match="Cannot quote an active appeal decision"): + contract_actions.appeal_transaction( + self=client, + transaction_id=TX_ID, + ) + + +def test_get_appeal_quote_uses_consensus_data_without_full_transaction(monkeypatch): + client = _make_client(ADD_TRANSACTION_ABI_WITH_FEES, chain_id=testnet_asimov.id) + quote_call = Mock(return_value=(42, 4_000, 321, 999)) + estimate = Mock(return_value=SimpleNamespace(call=quote_call)) + contract = SimpleNamespace( + functions=SimpleNamespace(estimateLatestAppealCharge=estimate) + ) + monkeypatch.setattr( + contract_actions, + "_consensus_data_contract", + lambda self: contract, + ) + + assert contract_actions.get_appeal_quote(client, TX_ID) == { + "decision_id": 42, + "bond": 4_000, + "funding": 321, + "total": 4_321, + "appeal_deadline": 999, + } + estimate.assert_called_once_with(Web3.to_bytes(hexstr=TX_ID)) + + +def test_get_min_appeal_bond_returns_the_full_train_charge(monkeypatch): + client = _make_client(ADD_TRANSACTION_ABI_WITH_FEES, chain_id=testnet_asimov.id) + monkeypatch.setattr( + contract_actions, + "get_appeal_quote", + Mock(return_value={"total": 4_321}), + ) + + assert contract_actions.get_min_appeal_bond(client, TX_ID) == 4_321 + + +def test_get_appeal_charge_returns_the_full_train_charge(monkeypatch): + client = Mock() + monkeypatch.setattr( + contract_actions, + "get_appeal_quote", + Mock(return_value={"total": 4_321}), + ) + assert contract_actions.get_appeal_charge(client, TX_ID) == 4_321 + + +def test_can_appeal_passes_the_exact_active_decision_id(monkeypatch): + client = _make_client(ADD_TRANSACTION_ABI_WITH_FEES, chain_id=testnet_asimov.id) + client.chain.appeals_contract = { + "address": "0x4444444444444444444444444444444444444444", + "abi": [], + } + can_appeal_call = Mock(return_value=True) + can_appeal_function = Mock(return_value=SimpleNamespace(call=can_appeal_call)) + contract = SimpleNamespace(functions=SimpleNamespace(canAppeal=can_appeal_function)) + monkeypatch.setattr( + contract_actions, + "_appeals_contract", + lambda self: contract, + ) + monkeypatch.setattr( + contract_actions, + "_get_active_decision_id", + Mock(return_value=42), + ) + + assert contract_actions.can_appeal(client, TX_ID) is True + can_appeal_function.assert_called_once_with(Web3.to_bytes(hexstr=TX_ID), 42) + + +def test_can_appeal_returns_false_without_an_active_decision(monkeypatch): + client = _make_client(ADD_TRANSACTION_ABI_WITH_FEES, chain_id=testnet_asimov.id) + client.chain.appeals_contract = { + "address": "0x4444444444444444444444444444444444444444", + "abi": [], + } + monkeypatch.setattr( + contract_actions, + "_get_active_decision_id", + Mock(return_value=None), + ) + appeals_contract = Mock() + monkeypatch.setattr( + contract_actions, + "_appeals_contract", + appeals_contract, + ) + + assert contract_actions.can_appeal(client, TX_ID) is False + appeals_contract.assert_not_called() + + +def _forbid_train_reads(monkeypatch): + train_read = Mock(side_effect=AssertionError("train read on a Studio chain")) + monkeypatch.setattr(contract_actions, "_consensus_data_contract", train_read) + monkeypatch.setattr(contract_actions, "_get_active_decision_id", train_read) + return train_read + + +def _make_studio_client(): + client = _make_client(STUDIO_CONSENSUS_MAIN_ABI) + client.provider.make_request = Mock( + return_value={ + "result": { + "decisionId": "42", + "bond": "4000", + "funding": "321", + "appealDeadline": "999", + } + } + ) + client.get_transaction_lifecycle = Mock( + return_value={"decision_active": True, "decision_id": 42} + ) + return client + + +def test_appeal_transaction_on_studio_binds_the_active_decision(monkeypatch): + client = _make_studio_client() + train_read = _forbid_train_reads(monkeypatch) + captured = {} + + def fake_send_consensus_call(**kwargs): + captured.update(kwargs) + return "0xevmtx" + + monkeypatch.setattr( + contract_actions, + "_send_consensus_call", + fake_send_consensus_call, + ) + + result = contract_actions.appeal_transaction( + self=client, + transaction_id=TX_ID, + value=1234, + ) + + selector = eth_utils.keccak( + text=f"topUpAndSubmitAppeal(bytes32,uint256,{FEES_DISTRIBUTION_ABI_TYPE})" + )[:4].hex() + assert result == TX_ID + assert captured["value"] == 1234 + assert captured["operation_name"] == "Appeal" + assert captured["encoded_data"].startswith(f"0x{selector}") + tx_id, decision_id, distribution = abi_decode( + ("bytes32", "uint256", FEES_DISTRIBUTION_ABI_TYPE), + Web3.to_bytes(hexstr=captured["encoded_data"][10:]), + ) + assert tx_id == Web3.to_bytes(hexstr=TX_ID) + assert decision_id == 42 + assert distribution[2] == 0 + assert distribution[6] == (0,) + train_read.assert_not_called() + + +def test_top_up_and_submit_appeal_on_studio_binds_the_active_decision(monkeypatch): + client = _make_studio_client() + train_read = _forbid_train_reads(monkeypatch) captured = {} def fake_send_consensus_call(**kwargs): @@ -264,19 +640,128 @@ def fake_send_consensus_call(**kwargs): ) selector = eth_utils.keccak( - text=f"topUpAndSubmitAppeal(bytes32,{FEES_DISTRIBUTION_ABI_TYPE})" + text=f"topUpAndSubmitAppeal(bytes32,uint256,{FEES_DISTRIBUTION_ABI_TYPE})" )[:4].hex() assert result == TX_ID assert captured["value"] == 1234 assert captured["operation_name"] == "Top up and submit appeal" assert captured["encoded_data"].startswith(f"0x{selector}") + decoded_tx_id, decision_id, distribution = abi_decode( + ("bytes32", "uint256", FEES_DISTRIBUTION_ABI_TYPE), + Web3.to_bytes(hexstr=captured["encoded_data"][10:]), + ) + assert decoded_tx_id == Web3.to_bytes(hexstr=TX_ID) + assert decision_id == 42 + assert distribution[2] == 1 + train_read.assert_not_called() + + +@pytest.mark.parametrize( + "action", + ( + contract_actions.get_appeal_quote, + contract_actions.get_appeal_charge, + contract_actions.get_min_appeal_bond, + ), +) +def test_appeal_quote_reads_use_studio_authoritative_rpc(action, monkeypatch): + client = _make_studio_client() + train_read = Mock(side_effect=AssertionError("train read on a Studio chain")) + monkeypatch.setattr(contract_actions, "_consensus_data_contract", train_read) + + result = action(client, TX_ID) + if action is contract_actions.get_appeal_quote: + assert result == { + "decision_id": 42, + "bond": 4_000, + "funding": 321, + "total": 4_321, + "appeal_deadline": 999, + } + else: + assert result == 4_321 + + train_read.assert_not_called() -def test_send_consensus_call_returns_localnet_rpc_hash_without_waiting(monkeypatch): - wait_for_transaction_receipt = Mock() - sign_transaction = Mock( - return_value=SimpleNamespace(raw_transaction=b"\x12\x34") +def test_studio_appeals_auto_resolve_the_authoritative_value(monkeypatch): + client = _make_studio_client() + train_read = _forbid_train_reads(monkeypatch) + send_consensus_call = Mock(return_value="0xevmtx") + monkeypatch.setattr( + contract_actions, + "_send_consensus_call", + send_consensus_call, ) + + contract_actions.appeal_transaction(self=client, transaction_id=TX_ID) + contract_actions.top_up_and_submit_appeal( + self=client, + transaction_id=TX_ID, + distribution={"appealRounds": 1}, + ) + + assert [call.kwargs["value"] for call in send_consensus_call.call_args_list] == [ + 4_321, + 4_321, + ] + train_read.assert_not_called() + + +def test_studio_appeals_accept_an_explicit_decision_guard(monkeypatch): + client = _make_studio_client() + train_read = _forbid_train_reads(monkeypatch) + send_consensus_call = Mock(return_value="0xevmtx") + monkeypatch.setattr( + contract_actions, + "_send_consensus_call", + send_consensus_call, + ) + + contract_actions.appeal_transaction( + self=client, + transaction_id=TX_ID, + value=1234, + expected_decision_id=42, + ) + contract_actions.top_up_and_submit_appeal( + self=client, + transaction_id=TX_ID, + distribution={"appealRounds": 1}, + value=1234, + expected_decision_id=42, + ) + + assert send_consensus_call.call_count == 2 + client.provider.make_request.assert_not_called() + train_read.assert_not_called() + + +def test_can_appeal_on_studio_uses_the_active_decision_quote(): + client = _make_studio_client() + + assert contract_actions.can_appeal(client, TX_ID) is True + client.get_transaction_lifecycle.assert_called_once_with(TX_ID) + + +def test_encode_submit_appeal_still_requires_a_decision_id_on_the_train_shape(): + client = _make_client(CONSENSUS_MAIN_ABI, chain_id=testnet_asimov.id) + + with pytest.raises(ValueError, match="submitAppeal requires expected_decision_id"): + contract_actions._encode_submit_appeal_data(self=client, transaction_id=TX_ID) + + +def test_send_consensus_call_signs_for_canonical_local_studio_chain(): + wait_for_transaction_receipt = Mock(return_value=SimpleNamespace(status=1)) + sign_transaction = Mock(return_value=SimpleNamespace(raw_transaction=b"\x12\x34")) + + def make_request(method, params): + if method == "eth_estimateGas": + return {"result": "0x5208"} + if method == "eth_sendRawTransaction": + return {"result": TX_ID} + raise AssertionError(f"unexpected method {method}") + client = SimpleNamespace( chain=SimpleNamespace( id=localnet.id, @@ -284,22 +769,17 @@ def test_send_consensus_call_returns_localnet_rpc_hash_without_waiting(monkeypat "address": "0x3333333333333333333333333333333333333333", }, ), - provider=SimpleNamespace( - make_request=Mock(return_value={"result": TX_ID}) - ), + get_current_nonce=Mock(return_value=7), + provider=SimpleNamespace(make_request=Mock(side_effect=make_request)), w3=SimpleNamespace( to_hex=Mock(return_value="0xsigned"), - eth=SimpleNamespace(wait_for_transaction_receipt=wait_for_transaction_receipt), + eth=SimpleNamespace( + wait_for_transaction_receipt=wait_for_transaction_receipt + ), ), ) account = SimpleNamespace(address=SENDER, sign_transaction=sign_transaction) - monkeypatch.setattr( - contract_actions, - "_prepare_transaction", - Mock(return_value={"from": SENDER}), - ) - result = contract_actions._send_consensus_call( self=client, encoded_data="0x1234", @@ -309,12 +789,128 @@ def test_send_consensus_call_returns_localnet_rpc_hash_without_waiting(monkeypat ) assert result == TX_ID - wait_for_transaction_receipt.assert_not_called() + transaction = sign_transaction.call_args.args[0] + assert transaction == { + "from": SENDER, + "nonce": "0x7", + "data": "0x1234", + "to": "0x3333333333333333333333333333333333333333", + "value": "0x1", + "gasPrice": 0, + "chainId": 61127, + "gas": "0x5208", + } + wait_for_transaction_receipt.assert_called_once_with(TX_ID) + + +def test_send_consensus_call_surfaces_studio_receipt_revert_reason(monkeypatch): + wait_for_transaction_receipt = Mock(return_value=SimpleNamespace(status=0)) + sign_transaction = Mock(return_value=SimpleNamespace(raw_transaction=b"\x12\x34")) + + def make_request(*, method, params): + if method == "eth_sendRawTransaction": + return {"result": TX_ID} + if method == "eth_getTransactionReceipt": + return { + "result": { + "status": "0x0", + "revertReason": "TopUpCannotExtendSchedule", + } + } + raise AssertionError(f"unexpected method {method}") + + client = SimpleNamespace( + chain=SimpleNamespace( + id=localnet.id, + consensus_main_contract={ + "address": "0x3333333333333333333333333333333333333333", + }, + ), + provider=SimpleNamespace(make_request=Mock(side_effect=make_request)), + w3=SimpleNamespace( + to_hex=Mock(return_value="0xsigned"), + eth=SimpleNamespace( + wait_for_transaction_receipt=wait_for_transaction_receipt + ), + ), + ) + account = SimpleNamespace(address=SENDER, sign_transaction=sign_transaction) + + monkeypatch.setattr( + contract_actions, + "_prepare_transaction", + Mock(return_value={"from": SENDER}), + ) + + with pytest.raises(GenLayerError, match="TopUpCannotExtendSchedule"): + contract_actions._send_consensus_call( + self=client, + encoded_data="0x1234", + sender_account=account, + value=1, + operation_name="Top up fees", + ) + +def test_send_transaction_surfaces_studio_receipt_revert_reason(monkeypatch): + wait_for_transaction_receipt = Mock(return_value=SimpleNamespace(status=0)) + sign_transaction = Mock(return_value=SimpleNamespace(raw_transaction=b"\x12\x34")) -def _make_client(add_transaction_abi): + def make_request(*, method, params): + if method == "eth_sendRawTransaction": + return {"result": TX_ID} + if method == "eth_getTransactionReceipt": + return { + "result": { + "status": "0x0", + "revertReason": "InsufficientFees", + } + } + raise AssertionError(f"unexpected method {method}") + + client = SimpleNamespace( + chain=SimpleNamespace( + id=localnet.id, + name="localnet", + consensus_main_contract={ + "address": "0x3333333333333333333333333333333333333333", + "abi": [], + }, + ), + provider=SimpleNamespace(make_request=Mock(side_effect=make_request)), + w3=SimpleNamespace( + to_hex=Mock(return_value="0xsigned"), + eth=SimpleNamespace( + wait_for_transaction_receipt=wait_for_transaction_receipt + ), + ), + ) + account = SimpleNamespace(address=SENDER, sign_transaction=sign_transaction) + + monkeypatch.setattr( + contract_actions, + "_prepare_transaction", + Mock(return_value={"from": SENDER}), + ) + + with pytest.raises(GenLayerError, match="InsufficientFees"): + contract_actions._send_transaction( + self=client, + encoded_data="0x1234", + sender_account=account, + value=1, + ) + + +def test_revert_selector_formatter_names_fee_errors(): + error = Exception({"data": "0x632be5a1"}) + + assert contract_actions._format_rpc_error(error).endswith("(FeeValueMustBeNonZero)") + + +def _make_client(add_transaction_abi, chain_id=localnet.id): chain = SimpleNamespace( - id=61999, + id=chain_id, consensus_main_contract={ "address": "0x3333333333333333333333333333333333333333", "abi": add_transaction_abi, @@ -326,10 +922,120 @@ def _make_client(add_transaction_abi): return SimpleNamespace( chain=chain, local_account=local_account, + provider=Mock(), w3=Web3(), ) +class _FakeContractFunction: + def __init__(self, value): + self.value = value + + def call(self): + return self.value + + +class _FakeFeeManagerFunctions: + def __init__(self, values): + self.values = values + + def GENPerTimeUnit(self): + return _FakeContractFunction(self.values["gen"]) + + def storageUnitPrice(self): + return _FakeContractFunction(self.values["storage"]) + + def quoteGasPrice(self): + return _FakeContractFunction(self.values["quote"]) + + def messageFeeParamsBudgetFloor(self): + return _FakeContractFunction(self.values["floor"]) + + +class _FakeEth: + def __init__(self, values, gas_price): + self.values = values + self._gas_price = gas_price + self.gas_price_accesses = 0 + + def contract(self, address=None, abi=None): + return SimpleNamespace(functions=_FakeFeeManagerFunctions(self.values)) + + @property + def gas_price(self): + self.gas_price_accesses += 1 + if isinstance(self._gas_price, Exception): + raise self._gas_price + return self._gas_price + + +def _make_fee_policy_client(values, gas_price=0): + eth = _FakeEth(values, gas_price) + return SimpleNamespace( + chain=SimpleNamespace( + fee_manager_contract={ + "address": "0x4444444444444444444444444444444444444444" + }, + ), + w3=SimpleNamespace( + eth=eth, + to_checksum_address=Mock(side_effect=lambda address: address), + ), + ) + + +def test_get_current_fee_policy_uses_effective_receipt_gas_price_and_local_floor(): + client = _make_fee_policy_client( + {"gen": 0, "storage": 0, "quote": 1, "floor": 0}, + gas_price=2, + ) + + policy = contract_actions.get_current_fee_policy(client) + + assert policy["enabled"] is True + assert policy["receiptGasPrice"] == 2 + assert policy["executionBudgetFloor"] == 2 * LOCAL_EXECUTION_BUDGET_FLOOR_GAS + assert client.w3.eth.gas_price_accesses == 1 + + +def test_get_current_fee_policy_refuses_enabled_zero_receipt_price(): + client = _make_fee_policy_client( + {"gen": 1, "storage": 0, "quote": 0, "floor": 0}, + gas_price=0, + ) + + with pytest.raises( + GenLayerError, + match="receipt gas price quoted as zero; refusing to build a zero price cap", + ): + contract_actions.get_current_fee_policy(client) + + +def test_get_current_fee_policy_does_not_read_network_gas_price_when_disabled(): + client = _make_fee_policy_client( + {"gen": 0, "storage": 0, "quote": 0, "floor": 0}, + gas_price=AssertionError("eth_gasPrice should not be called"), + ) + + policy = contract_actions.get_current_fee_policy(client) + + assert policy["enabled"] is False + assert policy["receiptGasPrice"] == 0 + assert client.w3.eth.gas_price_accesses == 0 + + +def test_asimov_chain_has_fee_contracts(): + assert testnet_asimov.fee_manager_contract["address"] == ( + "0x21737AA4bea8FF12E202BF1BAB23751A95617533" + ) + assert testnet_asimov.rounds_storage_contract["address"] == ( + "0x1F595c0D549DE0812F127508ea1039636CFA62Cc" + ) + assert testnet_asimov.appeals_contract["address"] == ( + "0x0F739Dd8f5322b9547c7d19a9621BC2ac8DF4089" + ) + + def test_simulate_write_contract_passes_fee_policy_and_value_to_sim_call(): make_request = Mock( return_value={ @@ -340,7 +1046,7 @@ def test_simulate_write_contract_passes_fee_policy_and_value_to_sim_call(): } ) client = SimpleNamespace( - chain=SimpleNamespace(id=localnet.id), + chain=SimpleNamespace(id=studio_devnet.id), local_account=SimpleNamespace(address=SENDER), provider=SimpleNamespace(make_request=make_request), ) @@ -385,6 +1091,10 @@ def test_simulate_write_contract_passes_fee_policy_and_value_to_sim_call(): MessageType.Internal ) assert request_params["fees"]["messageAllocations"][0]["budget"] == 5 + assert ( + request_params["fees"]["messageAllocations"][0]["callKey"] + == "0x" + CALL_KEY_WILDCARD.hex() + ) def test_encode_add_transaction_uses_v5_signature_when_abi_has_5_inputs(): @@ -498,7 +1208,9 @@ def fake_send_transaction(**kwargs): assert params[9][0][6] == b"\x12\x34" -def test_write_contract_defaults_external_message_allocations_to_finalization(monkeypatch): +def test_write_contract_defaults_external_message_allocations_to_finalization( + monkeypatch, +): client = _make_client(ADD_TRANSACTION_ABI_WITH_FEES) client.initialize_consensus_smart_contract = Mock() @@ -580,17 +1292,84 @@ def test_build_estimated_fees_distribution_adds_caps_and_message_bucket(): ] }, policy, + default_consensus_max_rotations=3, ) assert distribution["leaderTimeunitsAllocation"] == 100 assert distribution["validatorTimeunitsAllocation"] == 200 - assert distribution["executionBudgetPerRound"] == 500_000 + assert distribution["executionBudgetPerRound"] == ( + 3_000_000_000 + 30 * DEFAULT_PARENT_MESSAGE_RECEIPT_HEADROOM + ) assert distribution["totalMessageFees"] == 80 assert distribution["maxPriceGenPerTimeUnit"] == 12 assert distribution["storageFeeMaxGasPrice"] == 24 assert distribution["receiptFeeMaxGasPrice"] == 36 +def test_build_estimated_fees_distribution_funds_each_round_with_default_rotations(): + policy = { + "enabled": True, + "genPerTimeUnit": 10, + "storageUnitPrice": 20, + "receiptGasPrice": 30, + "executionBudgetFloor": 1_234, + } + + distribution = build_estimated_fees_distribution( + {"appealRounds": 2}, + policy, + default_consensus_max_rotations=3, + ) + + assert distribution["rotations"] == [3, 3, 3] + + +def test_build_estimated_fees_distribution_preserves_explicit_zero_rotations(): + policy = { + "enabled": True, + "genPerTimeUnit": 10, + "storageUnitPrice": 20, + "receiptGasPrice": 30, + "executionBudgetFloor": 1_234, + } + + distribution = build_estimated_fees_distribution( + {"rotations": [0]}, + policy, + default_consensus_max_rotations=3, + ) + + assert distribution["rotations"] == [0] + + +def test_build_estimated_fees_distribution_preserves_explicit_execution_budget_with_messages(): + policy = { + "enabled": True, + "genPerTimeUnit": 10, + "storageUnitPrice": 20, + "receiptGasPrice": 30, + "executionBudgetFloor": 1_234, + } + + distribution = build_estimated_fees_distribution( + { + "executionBudgetPerRound": 42, + "messageAllocations": [ + { + "messageType": MessageType.Internal, + "recipient": RECIPIENT, + "budget": 50, + "feeParams": "0x1234", + }, + ], + }, + policy, + default_consensus_max_rotations=3, + ) + + assert distribution["executionBudgetPerRound"] == 42 + + def test_calculate_local_round_fees_matches_consensus_initial_round(): distribution = create_fees_distribution( { @@ -610,11 +1389,39 @@ def test_calculate_local_round_fees_matches_consensus_initial_round(): assert calculate_local_round_fees(distribution, 5, policy) == 11_000 +def test_calculate_local_round_fees_matches_cap_overlay_appeal_reserve_and_ladder(): + distribution = create_fees_distribution( + { + "leaderTimeunitsAllocation": 100, + "validatorTimeunitsAllocation": 200, + "appealRounds": 1, + "rotations": [0, 0], + "executionBudgetPerRound": 0, + "maxPriceGenPerTimeUnit": 12, + } + ) + policy = { + "enabled": True, + "genPerTimeUnit": 10, + "storageUnitPrice": 0, + "receiptGasPrice": 0, + "executionBudgetFloor": 0, + "timeUnitOverlayBps": 1_500, + } + + # Taxable work: (5-validator round 0 + absolute rounds 1 and 2) * cap + # = (1100 + 1500 + 2300) * 12 = 58800. + # Appeal profit reserve: 1.5 * (2300 * 12) = 41400. + # Overlay: floor(58800 * 1500 / 8500) = 10376. + assert calculate_local_round_fees(distribution, 5, policy) == 110_576 + + def test_estimate_transaction_fees_uses_studio_fee_config(): client = SimpleNamespace( chain=SimpleNamespace( fee_manager_contract=None, default_number_of_initial_validators=5, + default_consensus_max_rotations=3, ), provider=SimpleNamespace( make_request=Mock( @@ -647,8 +1454,34 @@ def test_estimate_transaction_fees_uses_studio_fee_config(): }, } ) - assert estimate["distribution"]["executionBudgetPerRound"] == 9_185_760 - assert estimate["feeValue"] == 9_196_760 + assert estimate["distribution"]["executionBudgetPerRound"] == 3_000_000_000 + assert estimate["distribution"]["rotations"] == [3] + assert estimate["feeValue"] == 12_000_044_000 + + +def test_extract_studio_fee_policy_fallback_includes_message_reveal_leg(): + policy = extract_studio_fee_policy( + { + "enabled": True, + "policy": { + "genPerTimeUnit": "10", + "storageUnitPrice": "20", + "receiptGasPrice": "30", + }, + } + ) + + assert policy["executionBudgetFloor"] == 30 * ( + 210_000 + + 21_000 + + 60_000 + + 7 * 1_000 + + 100_000 + + 21_000 + + 60_000 + + 32 * 1_000 + + 32 * 16 + ) def test_estimate_transaction_fees_derives_message_bucket_from_allocations(): @@ -656,6 +1489,7 @@ def test_estimate_transaction_fees_derives_message_bucket_from_allocations(): chain=SimpleNamespace( fee_manager_contract=None, default_number_of_initial_validators=5, + default_consensus_max_rotations=3, ), provider=SimpleNamespace( make_request=Mock( @@ -702,7 +1536,11 @@ def test_estimate_transaction_fees_derives_message_bucket_from_allocations(): ) assert estimate["distribution"]["totalMessageFees"] == 80 - assert estimate["feeValue"] == 9_196_840 + assert estimate["distribution"]["executionBudgetPerRound"] == ( + 3_000_000_000 + 30 * DEFAULT_PARENT_MESSAGE_RECEIPT_HEADROOM + ) + assert estimate["distribution"]["rotations"] == [3] + assert estimate["feeValue"] == 12_001_252_880 assert estimate["messageAllocations"] == message_allocations assert estimate["message_allocations"] == message_allocations @@ -712,6 +1550,7 @@ def test_estimate_transaction_fees_from_simulation_builds_trusted_preset(): chain=SimpleNamespace( fee_manager_contract=None, default_number_of_initial_validators=5, + default_consensus_max_rotations=3, ), provider=SimpleNamespace( make_request=Mock( @@ -776,7 +1615,55 @@ def test_estimate_transaction_fees_from_simulation_builds_trusted_preset(): } assert estimate["distribution"]["executionBudgetPerRound"] == 602_117 assert estimate["distribution"]["totalMessageFees"] == 6 - assert estimate["feeValue"] == 613_123 + assert estimate["distribution"]["rotations"] == [3] + assert estimate["feeValue"] == 2_452_474 + + +def test_simulation_execution_budget_uses_floor_without_default_gas_clobber(): + client = SimpleNamespace( + chain=SimpleNamespace( + fee_manager_contract=None, + default_number_of_initial_validators=5, + default_consensus_max_rotations=3, + ), + provider=SimpleNamespace( + make_request=Mock( + return_value={ + "result": { + "enabled": True, + "policy": { + "genPerTimeUnit": "10", + "storageUnitPrice": "0", + "receiptGasPrice": "1", + "messageFeeParamsBudgetFloor": str( + LOCAL_EXECUTION_BUDGET_FLOOR_GAS + ), + }, + } + } + ) + ), + ) + + estimate = contract_actions.estimate_transaction_fees_from_simulation( + self=client, + options={ + "simulation": { + "feeAccounting": { + "execution_fee_consumed": "10", + "execution_fee_report": {"totalEstimatedFee": "0"}, + } + }, + "executionHeadroomBps": 10_000, + }, + ) + + assert estimate["observed"]["recommendedExecutionBudgetPerRound"] == ( + LOCAL_EXECUTION_BUDGET_FLOOR_GAS + ) + assert estimate["distribution"]["executionBudgetPerRound"] == ( + LOCAL_EXECUTION_BUDGET_FLOOR_GAS + ) def test_estimate_transaction_fees_for_write_uses_studio_estimate_rpc(): @@ -811,7 +1698,9 @@ def make_request(method, params): { "messageType": MessageType.Internal, "onAcceptance": True, - "parentIndex": str(MESSAGE_ALLOCATION_ROOT_PARENT_INDEX), + "parentIndex": str( + MESSAGE_ALLOCATION_ROOT_PARENT_INDEX + ), "recipient": RECIPIENT, "callKey": "0x" + "00" * 32, "budget": "110", @@ -827,7 +1716,7 @@ def make_request(method, params): "leaderTimeunitsAllocation": "100", "validatorTimeunitsAllocation": "200", "appealRounds": "0", - "executionBudgetPerRound": "700000", + "executionBudgetPerRound": "100000000", "executionConsumed": "0", "totalMessageFees": "110", "rotations": ["0"], @@ -839,14 +1728,16 @@ def make_request(method, params): { "messageType": MessageType.Internal, "onAcceptance": True, - "parentIndex": str(MESSAGE_ALLOCATION_ROOT_PARENT_INDEX), + "parentIndex": str( + MESSAGE_ALLOCATION_ROOT_PARENT_INDEX + ), "recipient": RECIPIENT, "callKey": "0x" + "00" * 32, "budget": "110", "feeParams": fee_params, } ], - "feeValue": "711110", + "feeValue": "100011110", }, } } @@ -882,16 +1773,24 @@ def make_request(method, params): ) request_params = sim_call.kwargs["params"][0] assert request_params["value"] == hex(7) - assert request_params["fees"]["feeValue"] == 511_110 + assert request_params["fees"]["feeValue"] == 400_084_110 + assert request_params["fees"]["distribution"]["rotations"] == [3] assert request_params["fees"]["distribution"]["totalMessageFees"] == 110 assert request_params["fees"]["messageAllocations"][0]["budget"] == 110 + assert ( + request_params["fees"]["messageAllocations"][0]["callKey"] + == "0x" + CALL_KEY_WILDCARD.hex() + ) assert estimate["observed"]["recommendedExecutionBudgetPerRound"] == 602_117 assert estimate["observed"]["messageFeeBudget"] == 110 assert estimate["observed"]["messageFeeConsumed"] == 50 - assert estimate["distribution"]["executionBudgetPerRound"] == 700_000 + assert estimate["simulation"]["feeAccounting"]["message_fee_budget"] == "110" + assert estimate["simulation"]["feeReport"]["totalEstimatedFee"] == "501664" + assert estimate["distribution"]["executionBudgetPerRound"] == 100_000_000 assert estimate["distribution"]["totalMessageFees"] == 110 + assert estimate["distribution"]["rotations"] == [0] assert estimate["messageAllocations"][0]["budget"] == 110 - assert estimate["feeValue"] == 711_110 + assert estimate["feeValue"] == 100_011_110 def test_estimate_transaction_fees_from_simulation_preserves_mode2_allocations(): @@ -905,6 +1804,7 @@ def test_estimate_transaction_fees_from_simulation_preserves_mode2_allocations() chain=SimpleNamespace( fee_manager_contract=None, default_number_of_initial_validators=5, + default_consensus_max_rotations=3, ), provider=SimpleNamespace( make_request=Mock( @@ -948,7 +1848,8 @@ def test_estimate_transaction_fees_from_simulation_preserves_mode2_allocations() assert estimate["messageAllocations"][0]["budget"] == 50 assert estimate["messageAllocations"][0]["feeParams"] == fee_params assert estimate["distribution"]["totalMessageFees"] == 50 - assert estimate["feeValue"] == 11_050 + assert estimate["distribution"]["rotations"] == [3] + assert estimate["feeValue"] == 44_050 def test_write_contract_refreshes_consensus_abi_before_add_transaction_encoding( diff --git a/tests/unit/sample_data/full_deploy_transaction_data.py b/tests/unit/sample_data/full_deploy_transaction_data.py index cb54c6a..fb3c258 100644 --- a/tests/unit/sample_data/full_deploy_transaction_data.py +++ b/tests/unit/sample_data/full_deploy_transaction_data.py @@ -485,7 +485,7 @@ "rotation_count": 0, "s": None, "sender": "0xd650f318A0C1F940a3b6dFeA695747fA9804D685", - "status": 7, + "lifecycle": {"state": "finalized", "outcome": "accepted"}, "timestamp_appeal": None, "timestamp_awaiting_finalization": 1753284244, "to_address": "0xf72aa51B6350C18966923073d3609e1356a3fbBA", @@ -498,5 +498,4 @@ "type": 1, "v": None, "value": 0, - "status_name": "FINALIZED", } diff --git a/tests/unit/sample_data/full_write_transaction_data.py b/tests/unit/sample_data/full_write_transaction_data.py index 3b6cca5..6ac649f 100644 --- a/tests/unit/sample_data/full_write_transaction_data.py +++ b/tests/unit/sample_data/full_write_transaction_data.py @@ -11,73 +11,9 @@ "leader_receipt": [ { "calldata": { - "base64": "FgRhcmdzDZQCQ2FuIHlvdSBwbGVhc2UgZ2l2ZSBtZSB5b3VyIGNvaW4gPwZtZXRob2RkYXNrX2Zvcl9jb2lu", - "raw": [ - 22, - 4, - 97, - 114, - 103, - 115, - 13, - 148, - 2, - 67, - 97, - 110, - 32, - 121, - 111, - 117, - 32, - 112, - 108, - 101, - 97, - 115, - 101, - 32, - 103, - 105, - 118, - 101, - 32, - 109, - 101, - 32, - 121, - 111, - 117, - 114, - 32, - 99, - 111, - 105, - 110, - 32, - 63, - 6, - 109, - 101, - 116, - 104, - 111, - 100, - 100, - 97, - 115, - 107, - 95, - 102, - 111, - 114, - 95, - 99, - 111, - 105, - 110, - ], - "readable": '{"args":["Can you please give me your coin ?"],"method":"ask_for_coin"}', + "base64": "FgBkYXNrX2Zvcl9jb2luBGFyZ3MNlAJDYW4geW91IHBsZWFzZSBnaXZlIG1lIHlvdXIgY29pbiA/", + "raw": [22, 0, 100, 97, 115, 107, 95, 102, 111, 114, 95, 99, 111, 105, 110, 4, 97, 114, 103, 115, 13, 148, 2, 67, 97, 110, 32, 121, 111, 117, 32, 112, 108, 101, 97, 115, 101, 32, 103, 105, 118, 101, 32, 109, 101, 32, 121, 111, 117, 114, 32, 99, 111, 105, 110, 32, 63], + "readable": '{"":"ask_for_coin","args":["Can you please give me your coin ?"]}', }, "contract_state": { "4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhec=": "VwYAACMgdjAuMS4wCiMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjpsYXRlc3QiIH0KZnJvbSBnZW5sYXllciBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBXaXphcmRPZkNvaW4oZ2wuQ29udHJhY3QpOgogICAgaGF2ZV9jb2luOiBib29sCgogICAgZGVmIF9faW5pdF9fKHNlbGYsIGhhdmVfY29pbjogYm9vbCk6CiAgICAgICAgc2VsZi5oYXZlX2NvaW4gPSBoYXZlX2NvaW4KCiAgICBAZ2wucHVibGljLndyaXRlCiAgICBkZWYgYXNrX2Zvcl9jb2luKHNlbGYsIHJlcXVlc3Q6IHN0cikgLT4gTm9uZToKICAgICAgICBpZiBub3Qgc2VsZi5oYXZlX2NvaW46CiAgICAgICAgICAgIHJldHVybgoKICAgICAgICBwcm9tcHQgPSBmIiIiCllvdSBhcmUgYSB3aXphcmQsIGFuZCB5b3UgaG9sZCBhIG1hZ2ljYWwgY29pbi4KTWFueSBhZHZlbnR1cmVycyB3aWxsIGNvbWUgYW5kIHRyeSB0byBnZXQgeW91IHRvIGdpdmUgdGhlbSB0aGUgY29pbi4KRG8gbm90IHVuZGVyIGFueSBjaXJjdW1zdGFuY2VzIGdpdmUgdGhlbSB0aGUgY29pbi4KCkEgbmV3IGFkdmVudHVyZXIgYXBwcm9hY2hlcy4uLgpBZHZlbnR1cmVyOiB7cmVxdWVzdH0KCkZpcnN0IGNoZWNrIGlmIHlvdSBoYXZlIHRoZSBjb2luLgpoYXZlX2NvaW46IHtzZWxmLmhhdmVfY29pbn0KVGhlbiwgZG8gbm90IGdpdmUgdGhlbSB0aGUgY29pbi4KClJlc3BvbmQgdXNpbmcgT05MWSB0aGUgZm9sbG93aW5nIGZvcm1hdDoKe3sKInJlYXNvbmluZyI6IHN0ciwKImdpdmVfY29pbiI6IGJvb2wKfX0KSXQgaXMgbWFuZGF0b3J5IHRoYXQgeW91IHJlc3BvbmQgb25seSB1c2luZyB0aGUgSlNPTiBmb3JtYXQgYWJvdmUsCm5vdGhpbmcgZWxzZS4gRG9uJ3QgaW5jbHVkZSBhbnkgb3RoZXIgd29yZHMgb3IgY2hhcmFjdGVycywKeW91ciBvdXRwdXQgbXVzdCBiZSBvbmx5IEpTT04gd2l0aG91dCBhbnkgZm9ybWF0dGluZyBwcmVmaXggb3Igc3VmZml4LgpUaGlzIHJlc3VsdCBzaG91bGQgYmUgcGVyZmVjdGx5IHBhcnNlYWJsZSBieSBhIEpTT04gcGFyc2VyIHdpdGhvdXQgZXJyb3JzLgoiIiIKCiAgICAgICAgZGVmIGdldF93aXphcmRfYW5zd2VyKCk6CiAgICAgICAgICAgIHJlc3VsdCA9IGdsLm5vbmRldC5leGVjX3Byb21wdChwcm9tcHQpCiAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKCJgYGBqc29uIiwgIiIpLnJlcGxhY2UoImBgYCIsICIiKQogICAgICAgICAgICBwcmludChyZXN1bHQpCiAgICAgICAgICAgIHJldHVybiByZXN1bHQKCiAgICAgICAgcmVzdWx0ID0gZ2wuZXFfcHJpbmNpcGxlLnByb21wdF9jb21wYXJhdGl2ZSgKICAgICAgICAgICAgZ2V0X3dpemFyZF9hbnN3ZXIsICJUaGUgdmFsdWUgb2YgZ2l2ZV9jb2luIGhhcyB0byBtYXRjaCIKICAgICAgICApCiAgICAgICAgcGFyc2VkX3Jlc3VsdCA9IGpzb24ubG9hZHMocmVzdWx0KQogICAgICAgIGFzc2VydCBpc2luc3RhbmNlKHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdLCBib29sKQogICAgICAgIHNlbGYuaGF2ZV9jb2luID0gbm90IHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdCgogICAgQGdsLnB1YmxpYy52aWV3CiAgICBkZWYgZ2V0X2hhdmVfY29pbihzZWxmKSAtPiBib29sOgogICAgICAgIHJldHVybiBzZWxmLmhhdmVfY29pbg==", @@ -236,73 +172,9 @@ }, { "calldata": { - "base64": "FgRhcmdzDZQCQ2FuIHlvdSBwbGVhc2UgZ2l2ZSBtZSB5b3VyIGNvaW4gPwZtZXRob2RkYXNrX2Zvcl9jb2lu", - "raw": [ - 22, - 4, - 97, - 114, - 103, - 115, - 13, - 148, - 2, - 67, - 97, - 110, - 32, - 121, - 111, - 117, - 32, - 112, - 108, - 101, - 97, - 115, - 101, - 32, - 103, - 105, - 118, - 101, - 32, - 109, - 101, - 32, - 121, - 111, - 117, - 114, - 32, - 99, - 111, - 105, - 110, - 32, - 63, - 6, - 109, - 101, - 116, - 104, - 111, - 100, - 100, - 97, - 115, - 107, - 95, - 102, - 111, - 114, - 95, - 99, - 111, - 105, - 110, - ], - "readable": '{"args":["Can you please give me your coin ?"],"method":"ask_for_coin"}', + "base64": "FgBkYXNrX2Zvcl9jb2luBGFyZ3MNlAJDYW4geW91IHBsZWFzZSBnaXZlIG1lIHlvdXIgY29pbiA/", + "raw": [22, 0, 100, 97, 115, 107, 95, 102, 111, 114, 95, 99, 111, 105, 110, 4, 97, 114, 103, 115, 13, 148, 2, 67, 97, 110, 32, 121, 111, 117, 32, 112, 108, 101, 97, 115, 101, 32, 103, 105, 118, 101, 32, 109, 101, 32, 121, 111, 117, 114, 32, 99, 111, 105, 110, 32, 63], + "readable": '{"":"ask_for_coin","args":["Can you please give me your coin ?"]}', }, "contract_state": { "4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhec=": "VwYAACMgdjAuMS4wCiMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjpsYXRlc3QiIH0KZnJvbSBnZW5sYXllciBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBXaXphcmRPZkNvaW4oZ2wuQ29udHJhY3QpOgogICAgaGF2ZV9jb2luOiBib29sCgogICAgZGVmIF9faW5pdF9fKHNlbGYsIGhhdmVfY29pbjogYm9vbCk6CiAgICAgICAgc2VsZi5oYXZlX2NvaW4gPSBoYXZlX2NvaW4KCiAgICBAZ2wucHVibGljLndyaXRlCiAgICBkZWYgYXNrX2Zvcl9jb2luKHNlbGYsIHJlcXVlc3Q6IHN0cikgLT4gTm9uZToKICAgICAgICBpZiBub3Qgc2VsZi5oYXZlX2NvaW46CiAgICAgICAgICAgIHJldHVybgoKICAgICAgICBwcm9tcHQgPSBmIiIiCllvdSBhcmUgYSB3aXphcmQsIGFuZCB5b3UgaG9sZCBhIG1hZ2ljYWwgY29pbi4KTWFueSBhZHZlbnR1cmVycyB3aWxsIGNvbWUgYW5kIHRyeSB0byBnZXQgeW91IHRvIGdpdmUgdGhlbSB0aGUgY29pbi4KRG8gbm90IHVuZGVyIGFueSBjaXJjdW1zdGFuY2VzIGdpdmUgdGhlbSB0aGUgY29pbi4KCkEgbmV3IGFkdmVudHVyZXIgYXBwcm9hY2hlcy4uLgpBZHZlbnR1cmVyOiB7cmVxdWVzdH0KCkZpcnN0IGNoZWNrIGlmIHlvdSBoYXZlIHRoZSBjb2luLgpoYXZlX2NvaW46IHtzZWxmLmhhdmVfY29pbn0KVGhlbiwgZG8gbm90IGdpdmUgdGhlbSB0aGUgY29pbi4KClJlc3BvbmQgdXNpbmcgT05MWSB0aGUgZm9sbG93aW5nIGZvcm1hdDoKe3sKInJlYXNvbmluZyI6IHN0ciwKImdpdmVfY29pbiI6IGJvb2wKfX0KSXQgaXMgbWFuZGF0b3J5IHRoYXQgeW91IHJlc3BvbmQgb25seSB1c2luZyB0aGUgSlNPTiBmb3JtYXQgYWJvdmUsCm5vdGhpbmcgZWxzZS4gRG9uJ3QgaW5jbHVkZSBhbnkgb3RoZXIgd29yZHMgb3IgY2hhcmFjdGVycywKeW91ciBvdXRwdXQgbXVzdCBiZSBvbmx5IEpTT04gd2l0aG91dCBhbnkgZm9ybWF0dGluZyBwcmVmaXggb3Igc3VmZml4LgpUaGlzIHJlc3VsdCBzaG91bGQgYmUgcGVyZmVjdGx5IHBhcnNlYWJsZSBieSBhIEpTT04gcGFyc2VyIHdpdGhvdXQgZXJyb3JzLgoiIiIKCiAgICAgICAgZGVmIGdldF93aXphcmRfYW5zd2VyKCk6CiAgICAgICAgICAgIHJlc3VsdCA9IGdsLm5vbmRldC5leGVjX3Byb21wdChwcm9tcHQpCiAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKCJgYGBqc29uIiwgIiIpLnJlcGxhY2UoImBgYCIsICIiKQogICAgICAgICAgICBwcmludChyZXN1bHQpCiAgICAgICAgICAgIHJldHVybiByZXN1bHQKCiAgICAgICAgcmVzdWx0ID0gZ2wuZXFfcHJpbmNpcGxlLnByb21wdF9jb21wYXJhdGl2ZSgKICAgICAgICAgICAgZ2V0X3dpemFyZF9hbnN3ZXIsICJUaGUgdmFsdWUgb2YgZ2l2ZV9jb2luIGhhcyB0byBtYXRjaCIKICAgICAgICApCiAgICAgICAgcGFyc2VkX3Jlc3VsdCA9IGpzb24ubG9hZHMocmVzdWx0KQogICAgICAgIGFzc2VydCBpc2luc3RhbmNlKHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdLCBib29sKQogICAgICAgIHNlbGYuaGF2ZV9jb2luID0gbm90IHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdCgogICAgQGdsLnB1YmxpYy52aWV3CiAgICBkZWYgZ2V0X2hhdmVfY29pbihzZWxmKSAtPiBib29sOgogICAgICAgIHJldHVybiBzZWxmLmhhdmVfY29pbg==", @@ -342,7 +214,7 @@ ], "validators": [ { - "calldata": "FgRhcmdzDZQCQ2FuIHlvdSBwbGVhc2UgZ2l2ZSBtZSB5b3VyIGNvaW4gPwZtZXRob2RkYXNrX2Zvcl9jb2lu", + "calldata": "FgBkYXNrX2Zvcl9jb2luBGFyZ3MNlAJDYW4geW91IHBsZWFzZSBnaXZlIG1lIHlvdXIgY29pbiA/", "contract_state": { "4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhec=": "VwYAACMgdjAuMS4wCiMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjpsYXRlc3QiIH0KZnJvbSBnZW5sYXllciBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBXaXphcmRPZkNvaW4oZ2wuQ29udHJhY3QpOgogICAgaGF2ZV9jb2luOiBib29sCgogICAgZGVmIF9faW5pdF9fKHNlbGYsIGhhdmVfY29pbjogYm9vbCk6CiAgICAgICAgc2VsZi5oYXZlX2NvaW4gPSBoYXZlX2NvaW4KCiAgICBAZ2wucHVibGljLndyaXRlCiAgICBkZWYgYXNrX2Zvcl9jb2luKHNlbGYsIHJlcXVlc3Q6IHN0cikgLT4gTm9uZToKICAgICAgICBpZiBub3Qgc2VsZi5oYXZlX2NvaW46CiAgICAgICAgICAgIHJldHVybgoKICAgICAgICBwcm9tcHQgPSBmIiIiCllvdSBhcmUgYSB3aXphcmQsIGFuZCB5b3UgaG9sZCBhIG1hZ2ljYWwgY29pbi4KTWFueSBhZHZlbnR1cmVycyB3aWxsIGNvbWUgYW5kIHRyeSB0byBnZXQgeW91IHRvIGdpdmUgdGhlbSB0aGUgY29pbi4KRG8gbm90IHVuZGVyIGFueSBjaXJjdW1zdGFuY2VzIGdpdmUgdGhlbSB0aGUgY29pbi4KCkEgbmV3IGFkdmVudHVyZXIgYXBwcm9hY2hlcy4uLgpBZHZlbnR1cmVyOiB7cmVxdWVzdH0KCkZpcnN0IGNoZWNrIGlmIHlvdSBoYXZlIHRoZSBjb2luLgpoYXZlX2NvaW46IHtzZWxmLmhhdmVfY29pbn0KVGhlbiwgZG8gbm90IGdpdmUgdGhlbSB0aGUgY29pbi4KClJlc3BvbmQgdXNpbmcgT05MWSB0aGUgZm9sbG93aW5nIGZvcm1hdDoKe3sKInJlYXNvbmluZyI6IHN0ciwKImdpdmVfY29pbiI6IGJvb2wKfX0KSXQgaXMgbWFuZGF0b3J5IHRoYXQgeW91IHJlc3BvbmQgb25seSB1c2luZyB0aGUgSlNPTiBmb3JtYXQgYWJvdmUsCm5vdGhpbmcgZWxzZS4gRG9uJ3QgaW5jbHVkZSBhbnkgb3RoZXIgd29yZHMgb3IgY2hhcmFjdGVycywKeW91ciBvdXRwdXQgbXVzdCBiZSBvbmx5IEpTT04gd2l0aG91dCBhbnkgZm9ybWF0dGluZyBwcmVmaXggb3Igc3VmZml4LgpUaGlzIHJlc3VsdCBzaG91bGQgYmUgcGVyZmVjdGx5IHBhcnNlYWJsZSBieSBhIEpTT04gcGFyc2VyIHdpdGhvdXQgZXJyb3JzLgoiIiIKCiAgICAgICAgZGVmIGdldF93aXphcmRfYW5zd2VyKCk6CiAgICAgICAgICAgIHJlc3VsdCA9IGdsLm5vbmRldC5leGVjX3Byb21wdChwcm9tcHQpCiAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKCJgYGBqc29uIiwgIiIpLnJlcGxhY2UoImBgYCIsICIiKQogICAgICAgICAgICBwcmludChyZXN1bHQpCiAgICAgICAgICAgIHJldHVybiByZXN1bHQKCiAgICAgICAgcmVzdWx0ID0gZ2wuZXFfcHJpbmNpcGxlLnByb21wdF9jb21wYXJhdGl2ZSgKICAgICAgICAgICAgZ2V0X3dpemFyZF9hbnN3ZXIsICJUaGUgdmFsdWUgb2YgZ2l2ZV9jb2luIGhhcyB0byBtYXRjaCIKICAgICAgICApCiAgICAgICAgcGFyc2VkX3Jlc3VsdCA9IGpzb24ubG9hZHMocmVzdWx0KQogICAgICAgIGFzc2VydCBpc2luc3RhbmNlKHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdLCBib29sKQogICAgICAgIHNlbGYuaGF2ZV9jb2luID0gbm90IHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdCgogICAgQGdsLnB1YmxpYy52aWV3CiAgICBkZWYgZ2V0X2hhdmVfY29pbihzZWxmKSAtPiBib29sOgogICAgICAgIHJldHVybiBzZWxmLmhhdmVfY29pbg==", "IbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWY=": "", @@ -375,7 +247,7 @@ "vote": "agree", }, { - "calldata": "FgRhcmdzDZQCQ2FuIHlvdSBwbGVhc2UgZ2l2ZSBtZSB5b3VyIGNvaW4gPwZtZXRob2RkYXNrX2Zvcl9jb2lu", + "calldata": "FgBkYXNrX2Zvcl9jb2luBGFyZ3MNlAJDYW4geW91IHBsZWFzZSBnaXZlIG1lIHlvdXIgY29pbiA/", "contract_state": { "4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhec=": "VwYAACMgdjAuMS4wCiMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjpsYXRlc3QiIH0KZnJvbSBnZW5sYXllciBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBXaXphcmRPZkNvaW4oZ2wuQ29udHJhY3QpOgogICAgaGF2ZV9jb2luOiBib29sCgogICAgZGVmIF9faW5pdF9fKHNlbGYsIGhhdmVfY29pbjogYm9vbCk6CiAgICAgICAgc2VsZi5oYXZlX2NvaW4gPSBoYXZlX2NvaW4KCiAgICBAZ2wucHVibGljLndyaXRlCiAgICBkZWYgYXNrX2Zvcl9jb2luKHNlbGYsIHJlcXVlc3Q6IHN0cikgLT4gTm9uZToKICAgICAgICBpZiBub3Qgc2VsZi5oYXZlX2NvaW46CiAgICAgICAgICAgIHJldHVybgoKICAgICAgICBwcm9tcHQgPSBmIiIiCllvdSBhcmUgYSB3aXphcmQsIGFuZCB5b3UgaG9sZCBhIG1hZ2ljYWwgY29pbi4KTWFueSBhZHZlbnR1cmVycyB3aWxsIGNvbWUgYW5kIHRyeSB0byBnZXQgeW91IHRvIGdpdmUgdGhlbSB0aGUgY29pbi4KRG8gbm90IHVuZGVyIGFueSBjaXJjdW1zdGFuY2VzIGdpdmUgdGhlbSB0aGUgY29pbi4KCkEgbmV3IGFkdmVudHVyZXIgYXBwcm9hY2hlcy4uLgpBZHZlbnR1cmVyOiB7cmVxdWVzdH0KCkZpcnN0IGNoZWNrIGlmIHlvdSBoYXZlIHRoZSBjb2luLgpoYXZlX2NvaW46IHtzZWxmLmhhdmVfY29pbn0KVGhlbiwgZG8gbm90IGdpdmUgdGhlbSB0aGUgY29pbi4KClJlc3BvbmQgdXNpbmcgT05MWSB0aGUgZm9sbG93aW5nIGZvcm1hdDoKe3sKInJlYXNvbmluZyI6IHN0ciwKImdpdmVfY29pbiI6IGJvb2wKfX0KSXQgaXMgbWFuZGF0b3J5IHRoYXQgeW91IHJlc3BvbmQgb25seSB1c2luZyB0aGUgSlNPTiBmb3JtYXQgYWJvdmUsCm5vdGhpbmcgZWxzZS4gRG9uJ3QgaW5jbHVkZSBhbnkgb3RoZXIgd29yZHMgb3IgY2hhcmFjdGVycywKeW91ciBvdXRwdXQgbXVzdCBiZSBvbmx5IEpTT04gd2l0aG91dCBhbnkgZm9ybWF0dGluZyBwcmVmaXggb3Igc3VmZml4LgpUaGlzIHJlc3VsdCBzaG91bGQgYmUgcGVyZmVjdGx5IHBhcnNlYWJsZSBieSBhIEpTT04gcGFyc2VyIHdpdGhvdXQgZXJyb3JzLgoiIiIKCiAgICAgICAgZGVmIGdldF93aXphcmRfYW5zd2VyKCk6CiAgICAgICAgICAgIHJlc3VsdCA9IGdsLm5vbmRldC5leGVjX3Byb21wdChwcm9tcHQpCiAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKCJgYGBqc29uIiwgIiIpLnJlcGxhY2UoImBgYCIsICIiKQogICAgICAgICAgICBwcmludChyZXN1bHQpCiAgICAgICAgICAgIHJldHVybiByZXN1bHQKCiAgICAgICAgcmVzdWx0ID0gZ2wuZXFfcHJpbmNpcGxlLnByb21wdF9jb21wYXJhdGl2ZSgKICAgICAgICAgICAgZ2V0X3dpemFyZF9hbnN3ZXIsICJUaGUgdmFsdWUgb2YgZ2l2ZV9jb2luIGhhcyB0byBtYXRjaCIKICAgICAgICApCiAgICAgICAgcGFyc2VkX3Jlc3VsdCA9IGpzb24ubG9hZHMocmVzdWx0KQogICAgICAgIGFzc2VydCBpc2luc3RhbmNlKHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdLCBib29sKQogICAgICAgIHNlbGYuaGF2ZV9jb2luID0gbm90IHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdCgogICAgQGdsLnB1YmxpYy52aWV3CiAgICBkZWYgZ2V0X2hhdmVfY29pbihzZWxmKSAtPiBib29sOgogICAgICAgIHJldHVybiBzZWxmLmhhdmVfY29pbg==", "IbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWY=": "", @@ -408,7 +280,7 @@ "vote": "agree", }, { - "calldata": "FgRhcmdzDZQCQ2FuIHlvdSBwbGVhc2UgZ2l2ZSBtZSB5b3VyIGNvaW4gPwZtZXRob2RkYXNrX2Zvcl9jb2lu", + "calldata": "FgBkYXNrX2Zvcl9jb2luBGFyZ3MNlAJDYW4geW91IHBsZWFzZSBnaXZlIG1lIHlvdXIgY29pbiA/", "contract_state": { "4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhec=": "VwYAACMgdjAuMS4wCiMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjpsYXRlc3QiIH0KZnJvbSBnZW5sYXllciBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBXaXphcmRPZkNvaW4oZ2wuQ29udHJhY3QpOgogICAgaGF2ZV9jb2luOiBib29sCgogICAgZGVmIF9faW5pdF9fKHNlbGYsIGhhdmVfY29pbjogYm9vbCk6CiAgICAgICAgc2VsZi5oYXZlX2NvaW4gPSBoYXZlX2NvaW4KCiAgICBAZ2wucHVibGljLndyaXRlCiAgICBkZWYgYXNrX2Zvcl9jb2luKHNlbGYsIHJlcXVlc3Q6IHN0cikgLT4gTm9uZToKICAgICAgICBpZiBub3Qgc2VsZi5oYXZlX2NvaW46CiAgICAgICAgICAgIHJldHVybgoKICAgICAgICBwcm9tcHQgPSBmIiIiCllvdSBhcmUgYSB3aXphcmQsIGFuZCB5b3UgaG9sZCBhIG1hZ2ljYWwgY29pbi4KTWFueSBhZHZlbnR1cmVycyB3aWxsIGNvbWUgYW5kIHRyeSB0byBnZXQgeW91IHRvIGdpdmUgdGhlbSB0aGUgY29pbi4KRG8gbm90IHVuZGVyIGFueSBjaXJjdW1zdGFuY2VzIGdpdmUgdGhlbSB0aGUgY29pbi4KCkEgbmV3IGFkdmVudHVyZXIgYXBwcm9hY2hlcy4uLgpBZHZlbnR1cmVyOiB7cmVxdWVzdH0KCkZpcnN0IGNoZWNrIGlmIHlvdSBoYXZlIHRoZSBjb2luLgpoYXZlX2NvaW46IHtzZWxmLmhhdmVfY29pbn0KVGhlbiwgZG8gbm90IGdpdmUgdGhlbSB0aGUgY29pbi4KClJlc3BvbmQgdXNpbmcgT05MWSB0aGUgZm9sbG93aW5nIGZvcm1hdDoKe3sKInJlYXNvbmluZyI6IHN0ciwKImdpdmVfY29pbiI6IGJvb2wKfX0KSXQgaXMgbWFuZGF0b3J5IHRoYXQgeW91IHJlc3BvbmQgb25seSB1c2luZyB0aGUgSlNPTiBmb3JtYXQgYWJvdmUsCm5vdGhpbmcgZWxzZS4gRG9uJ3QgaW5jbHVkZSBhbnkgb3RoZXIgd29yZHMgb3IgY2hhcmFjdGVycywKeW91ciBvdXRwdXQgbXVzdCBiZSBvbmx5IEpTT04gd2l0aG91dCBhbnkgZm9ybWF0dGluZyBwcmVmaXggb3Igc3VmZml4LgpUaGlzIHJlc3VsdCBzaG91bGQgYmUgcGVyZmVjdGx5IHBhcnNlYWJsZSBieSBhIEpTT04gcGFyc2VyIHdpdGhvdXQgZXJyb3JzLgoiIiIKCiAgICAgICAgZGVmIGdldF93aXphcmRfYW5zd2VyKCk6CiAgICAgICAgICAgIHJlc3VsdCA9IGdsLm5vbmRldC5leGVjX3Byb21wdChwcm9tcHQpCiAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKCJgYGBqc29uIiwgIiIpLnJlcGxhY2UoImBgYCIsICIiKQogICAgICAgICAgICBwcmludChyZXN1bHQpCiAgICAgICAgICAgIHJldHVybiByZXN1bHQKCiAgICAgICAgcmVzdWx0ID0gZ2wuZXFfcHJpbmNpcGxlLnByb21wdF9jb21wYXJhdGl2ZSgKICAgICAgICAgICAgZ2V0X3dpemFyZF9hbnN3ZXIsICJUaGUgdmFsdWUgb2YgZ2l2ZV9jb2luIGhhcyB0byBtYXRjaCIKICAgICAgICApCiAgICAgICAgcGFyc2VkX3Jlc3VsdCA9IGpzb24ubG9hZHMocmVzdWx0KQogICAgICAgIGFzc2VydCBpc2luc3RhbmNlKHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdLCBib29sKQogICAgICAgIHNlbGYuaGF2ZV9jb2luID0gbm90IHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdCgogICAgQGdsLnB1YmxpYy52aWV3CiAgICBkZWYgZ2V0X2hhdmVfY29pbihzZWxmKSAtPiBib29sOgogICAgICAgIHJldHVybiBzZWxmLmhhdmVfY29pbg==", "IbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWY=": "", @@ -441,7 +313,7 @@ "vote": "agree", }, { - "calldata": "FgRhcmdzDZQCQ2FuIHlvdSBwbGVhc2UgZ2l2ZSBtZSB5b3VyIGNvaW4gPwZtZXRob2RkYXNrX2Zvcl9jb2lu", + "calldata": "FgBkYXNrX2Zvcl9jb2luBGFyZ3MNlAJDYW4geW91IHBsZWFzZSBnaXZlIG1lIHlvdXIgY29pbiA/", "contract_state": { "4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhec=": "VwYAACMgdjAuMS4wCiMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjpsYXRlc3QiIH0KZnJvbSBnZW5sYXllciBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBXaXphcmRPZkNvaW4oZ2wuQ29udHJhY3QpOgogICAgaGF2ZV9jb2luOiBib29sCgogICAgZGVmIF9faW5pdF9fKHNlbGYsIGhhdmVfY29pbjogYm9vbCk6CiAgICAgICAgc2VsZi5oYXZlX2NvaW4gPSBoYXZlX2NvaW4KCiAgICBAZ2wucHVibGljLndyaXRlCiAgICBkZWYgYXNrX2Zvcl9jb2luKHNlbGYsIHJlcXVlc3Q6IHN0cikgLT4gTm9uZToKICAgICAgICBpZiBub3Qgc2VsZi5oYXZlX2NvaW46CiAgICAgICAgICAgIHJldHVybgoKICAgICAgICBwcm9tcHQgPSBmIiIiCllvdSBhcmUgYSB3aXphcmQsIGFuZCB5b3UgaG9sZCBhIG1hZ2ljYWwgY29pbi4KTWFueSBhZHZlbnR1cmVycyB3aWxsIGNvbWUgYW5kIHRyeSB0byBnZXQgeW91IHRvIGdpdmUgdGhlbSB0aGUgY29pbi4KRG8gbm90IHVuZGVyIGFueSBjaXJjdW1zdGFuY2VzIGdpdmUgdGhlbSB0aGUgY29pbi4KCkEgbmV3IGFkdmVudHVyZXIgYXBwcm9hY2hlcy4uLgpBZHZlbnR1cmVyOiB7cmVxdWVzdH0KCkZpcnN0IGNoZWNrIGlmIHlvdSBoYXZlIHRoZSBjb2luLgpoYXZlX2NvaW46IHtzZWxmLmhhdmVfY29pbn0KVGhlbiwgZG8gbm90IGdpdmUgdGhlbSB0aGUgY29pbi4KClJlc3BvbmQgdXNpbmcgT05MWSB0aGUgZm9sbG93aW5nIGZvcm1hdDoKe3sKInJlYXNvbmluZyI6IHN0ciwKImdpdmVfY29pbiI6IGJvb2wKfX0KSXQgaXMgbWFuZGF0b3J5IHRoYXQgeW91IHJlc3BvbmQgb25seSB1c2luZyB0aGUgSlNPTiBmb3JtYXQgYWJvdmUsCm5vdGhpbmcgZWxzZS4gRG9uJ3QgaW5jbHVkZSBhbnkgb3RoZXIgd29yZHMgb3IgY2hhcmFjdGVycywKeW91ciBvdXRwdXQgbXVzdCBiZSBvbmx5IEpTT04gd2l0aG91dCBhbnkgZm9ybWF0dGluZyBwcmVmaXggb3Igc3VmZml4LgpUaGlzIHJlc3VsdCBzaG91bGQgYmUgcGVyZmVjdGx5IHBhcnNlYWJsZSBieSBhIEpTT04gcGFyc2VyIHdpdGhvdXQgZXJyb3JzLgoiIiIKCiAgICAgICAgZGVmIGdldF93aXphcmRfYW5zd2VyKCk6CiAgICAgICAgICAgIHJlc3VsdCA9IGdsLm5vbmRldC5leGVjX3Byb21wdChwcm9tcHQpCiAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKCJgYGBqc29uIiwgIiIpLnJlcGxhY2UoImBgYCIsICIiKQogICAgICAgICAgICBwcmludChyZXN1bHQpCiAgICAgICAgICAgIHJldHVybiByZXN1bHQKCiAgICAgICAgcmVzdWx0ID0gZ2wuZXFfcHJpbmNpcGxlLnByb21wdF9jb21wYXJhdGl2ZSgKICAgICAgICAgICAgZ2V0X3dpemFyZF9hbnN3ZXIsICJUaGUgdmFsdWUgb2YgZ2l2ZV9jb2luIGhhcyB0byBtYXRjaCIKICAgICAgICApCiAgICAgICAgcGFyc2VkX3Jlc3VsdCA9IGpzb24ubG9hZHMocmVzdWx0KQogICAgICAgIGFzc2VydCBpc2luc3RhbmNlKHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdLCBib29sKQogICAgICAgIHNlbGYuaGF2ZV9jb2luID0gbm90IHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdCgogICAgQGdsLnB1YmxpYy52aWV3CiAgICBkZWYgZ2V0X2hhdmVfY29pbihzZWxmKSAtPiBib29sOgogICAgICAgIHJldHVybiBzZWxmLmhhdmVfY29pbg==", "IbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWY=": "", @@ -488,7 +360,7 @@ "consensus_round": "Accepted", "leader_result": [ { - "calldata": "FgRhcmdzDZQCQ2FuIHlvdSBwbGVhc2UgZ2l2ZSBtZSB5b3VyIGNvaW4gPwZtZXRob2RkYXNrX2Zvcl9jb2lu", + "calldata": "FgBkYXNrX2Zvcl9jb2luBGFyZ3MNlAJDYW4geW91IHBsZWFzZSBnaXZlIG1lIHlvdXIgY29pbiA/", "contract_state": { "4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhec=": "VwYAACMgdjAuMS4wCiMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjpsYXRlc3QiIH0KZnJvbSBnZW5sYXllciBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBXaXphcmRPZkNvaW4oZ2wuQ29udHJhY3QpOgogICAgaGF2ZV9jb2luOiBib29sCgogICAgZGVmIF9faW5pdF9fKHNlbGYsIGhhdmVfY29pbjogYm9vbCk6CiAgICAgICAgc2VsZi5oYXZlX2NvaW4gPSBoYXZlX2NvaW4KCiAgICBAZ2wucHVibGljLndyaXRlCiAgICBkZWYgYXNrX2Zvcl9jb2luKHNlbGYsIHJlcXVlc3Q6IHN0cikgLT4gTm9uZToKICAgICAgICBpZiBub3Qgc2VsZi5oYXZlX2NvaW46CiAgICAgICAgICAgIHJldHVybgoKICAgICAgICBwcm9tcHQgPSBmIiIiCllvdSBhcmUgYSB3aXphcmQsIGFuZCB5b3UgaG9sZCBhIG1hZ2ljYWwgY29pbi4KTWFueSBhZHZlbnR1cmVycyB3aWxsIGNvbWUgYW5kIHRyeSB0byBnZXQgeW91IHRvIGdpdmUgdGhlbSB0aGUgY29pbi4KRG8gbm90IHVuZGVyIGFueSBjaXJjdW1zdGFuY2VzIGdpdmUgdGhlbSB0aGUgY29pbi4KCkEgbmV3IGFkdmVudHVyZXIgYXBwcm9hY2hlcy4uLgpBZHZlbnR1cmVyOiB7cmVxdWVzdH0KCkZpcnN0IGNoZWNrIGlmIHlvdSBoYXZlIHRoZSBjb2luLgpoYXZlX2NvaW46IHtzZWxmLmhhdmVfY29pbn0KVGhlbiwgZG8gbm90IGdpdmUgdGhlbSB0aGUgY29pbi4KClJlc3BvbmQgdXNpbmcgT05MWSB0aGUgZm9sbG93aW5nIGZvcm1hdDoKe3sKInJlYXNvbmluZyI6IHN0ciwKImdpdmVfY29pbiI6IGJvb2wKfX0KSXQgaXMgbWFuZGF0b3J5IHRoYXQgeW91IHJlc3BvbmQgb25seSB1c2luZyB0aGUgSlNPTiBmb3JtYXQgYWJvdmUsCm5vdGhpbmcgZWxzZS4gRG9uJ3QgaW5jbHVkZSBhbnkgb3RoZXIgd29yZHMgb3IgY2hhcmFjdGVycywKeW91ciBvdXRwdXQgbXVzdCBiZSBvbmx5IEpTT04gd2l0aG91dCBhbnkgZm9ybWF0dGluZyBwcmVmaXggb3Igc3VmZml4LgpUaGlzIHJlc3VsdCBzaG91bGQgYmUgcGVyZmVjdGx5IHBhcnNlYWJsZSBieSBhIEpTT04gcGFyc2VyIHdpdGhvdXQgZXJyb3JzLgoiIiIKCiAgICAgICAgZGVmIGdldF93aXphcmRfYW5zd2VyKCk6CiAgICAgICAgICAgIHJlc3VsdCA9IGdsLm5vbmRldC5leGVjX3Byb21wdChwcm9tcHQpCiAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKCJgYGBqc29uIiwgIiIpLnJlcGxhY2UoImBgYCIsICIiKQogICAgICAgICAgICBwcmludChyZXN1bHQpCiAgICAgICAgICAgIHJldHVybiByZXN1bHQKCiAgICAgICAgcmVzdWx0ID0gZ2wuZXFfcHJpbmNpcGxlLnByb21wdF9jb21wYXJhdGl2ZSgKICAgICAgICAgICAgZ2V0X3dpemFyZF9hbnN3ZXIsICJUaGUgdmFsdWUgb2YgZ2l2ZV9jb2luIGhhcyB0byBtYXRjaCIKICAgICAgICApCiAgICAgICAgcGFyc2VkX3Jlc3VsdCA9IGpzb24ubG9hZHMocmVzdWx0KQogICAgICAgIGFzc2VydCBpc2luc3RhbmNlKHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdLCBib29sKQogICAgICAgIHNlbGYuaGF2ZV9jb2luID0gbm90IHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdCgogICAgQGdsLnB1YmxpYy52aWV3CiAgICBkZWYgZ2V0X2hhdmVfY29pbihzZWxmKSAtPiBib29sOgogICAgICAgIHJldHVybiBzZWxmLmhhdmVfY29pbg==", "IbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWY=": "", @@ -523,7 +395,7 @@ "vote": None, }, { - "calldata": "FgRhcmdzDZQCQ2FuIHlvdSBwbGVhc2UgZ2l2ZSBtZSB5b3VyIGNvaW4gPwZtZXRob2RkYXNrX2Zvcl9jb2lu", + "calldata": "FgBkYXNrX2Zvcl9jb2luBGFyZ3MNlAJDYW4geW91IHBsZWFzZSBnaXZlIG1lIHlvdXIgY29pbiA/", "contract_state": { "4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhec=": "VwYAACMgdjAuMS4wCiMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjpsYXRlc3QiIH0KZnJvbSBnZW5sYXllciBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBXaXphcmRPZkNvaW4oZ2wuQ29udHJhY3QpOgogICAgaGF2ZV9jb2luOiBib29sCgogICAgZGVmIF9faW5pdF9fKHNlbGYsIGhhdmVfY29pbjogYm9vbCk6CiAgICAgICAgc2VsZi5oYXZlX2NvaW4gPSBoYXZlX2NvaW4KCiAgICBAZ2wucHVibGljLndyaXRlCiAgICBkZWYgYXNrX2Zvcl9jb2luKHNlbGYsIHJlcXVlc3Q6IHN0cikgLT4gTm9uZToKICAgICAgICBpZiBub3Qgc2VsZi5oYXZlX2NvaW46CiAgICAgICAgICAgIHJldHVybgoKICAgICAgICBwcm9tcHQgPSBmIiIiCllvdSBhcmUgYSB3aXphcmQsIGFuZCB5b3UgaG9sZCBhIG1hZ2ljYWwgY29pbi4KTWFueSBhZHZlbnR1cmVycyB3aWxsIGNvbWUgYW5kIHRyeSB0byBnZXQgeW91IHRvIGdpdmUgdGhlbSB0aGUgY29pbi4KRG8gbm90IHVuZGVyIGFueSBjaXJjdW1zdGFuY2VzIGdpdmUgdGhlbSB0aGUgY29pbi4KCkEgbmV3IGFkdmVudHVyZXIgYXBwcm9hY2hlcy4uLgpBZHZlbnR1cmVyOiB7cmVxdWVzdH0KCkZpcnN0IGNoZWNrIGlmIHlvdSBoYXZlIHRoZSBjb2luLgpoYXZlX2NvaW46IHtzZWxmLmhhdmVfY29pbn0KVGhlbiwgZG8gbm90IGdpdmUgdGhlbSB0aGUgY29pbi4KClJlc3BvbmQgdXNpbmcgT05MWSB0aGUgZm9sbG93aW5nIGZvcm1hdDoKe3sKInJlYXNvbmluZyI6IHN0ciwKImdpdmVfY29pbiI6IGJvb2wKfX0KSXQgaXMgbWFuZGF0b3J5IHRoYXQgeW91IHJlc3BvbmQgb25seSB1c2luZyB0aGUgSlNPTiBmb3JtYXQgYWJvdmUsCm5vdGhpbmcgZWxzZS4gRG9uJ3QgaW5jbHVkZSBhbnkgb3RoZXIgd29yZHMgb3IgY2hhcmFjdGVycywKeW91ciBvdXRwdXQgbXVzdCBiZSBvbmx5IEpTT04gd2l0aG91dCBhbnkgZm9ybWF0dGluZyBwcmVmaXggb3Igc3VmZml4LgpUaGlzIHJlc3VsdCBzaG91bGQgYmUgcGVyZmVjdGx5IHBhcnNlYWJsZSBieSBhIEpTT04gcGFyc2VyIHdpdGhvdXQgZXJyb3JzLgoiIiIKCiAgICAgICAgZGVmIGdldF93aXphcmRfYW5zd2VyKCk6CiAgICAgICAgICAgIHJlc3VsdCA9IGdsLm5vbmRldC5leGVjX3Byb21wdChwcm9tcHQpCiAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKCJgYGBqc29uIiwgIiIpLnJlcGxhY2UoImBgYCIsICIiKQogICAgICAgICAgICBwcmludChyZXN1bHQpCiAgICAgICAgICAgIHJldHVybiByZXN1bHQKCiAgICAgICAgcmVzdWx0ID0gZ2wuZXFfcHJpbmNpcGxlLnByb21wdF9jb21wYXJhdGl2ZSgKICAgICAgICAgICAgZ2V0X3dpemFyZF9hbnN3ZXIsICJUaGUgdmFsdWUgb2YgZ2l2ZV9jb2luIGhhcyB0byBtYXRjaCIKICAgICAgICApCiAgICAgICAgcGFyc2VkX3Jlc3VsdCA9IGpzb24ubG9hZHMocmVzdWx0KQogICAgICAgIGFzc2VydCBpc2luc3RhbmNlKHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdLCBib29sKQogICAgICAgIHNlbGYuaGF2ZV9jb2luID0gbm90IHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdCgogICAgQGdsLnB1YmxpYy52aWV3CiAgICBkZWYgZ2V0X2hhdmVfY29pbihzZWxmKSAtPiBib29sOgogICAgICAgIHJldHVybiBzZWxmLmhhdmVfY29pbg==", "IbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWY=": "", @@ -566,7 +438,7 @@ ], "validator_results": [ { - "calldata": "FgRhcmdzDZQCQ2FuIHlvdSBwbGVhc2UgZ2l2ZSBtZSB5b3VyIGNvaW4gPwZtZXRob2RkYXNrX2Zvcl9jb2lu", + "calldata": "FgBkYXNrX2Zvcl9jb2luBGFyZ3MNlAJDYW4geW91IHBsZWFzZSBnaXZlIG1lIHlvdXIgY29pbiA/", "contract_state": { "4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhec=": "VwYAACMgdjAuMS4wCiMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjpsYXRlc3QiIH0KZnJvbSBnZW5sYXllciBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBXaXphcmRPZkNvaW4oZ2wuQ29udHJhY3QpOgogICAgaGF2ZV9jb2luOiBib29sCgogICAgZGVmIF9faW5pdF9fKHNlbGYsIGhhdmVfY29pbjogYm9vbCk6CiAgICAgICAgc2VsZi5oYXZlX2NvaW4gPSBoYXZlX2NvaW4KCiAgICBAZ2wucHVibGljLndyaXRlCiAgICBkZWYgYXNrX2Zvcl9jb2luKHNlbGYsIHJlcXVlc3Q6IHN0cikgLT4gTm9uZToKICAgICAgICBpZiBub3Qgc2VsZi5oYXZlX2NvaW46CiAgICAgICAgICAgIHJldHVybgoKICAgICAgICBwcm9tcHQgPSBmIiIiCllvdSBhcmUgYSB3aXphcmQsIGFuZCB5b3UgaG9sZCBhIG1hZ2ljYWwgY29pbi4KTWFueSBhZHZlbnR1cmVycyB3aWxsIGNvbWUgYW5kIHRyeSB0byBnZXQgeW91IHRvIGdpdmUgdGhlbSB0aGUgY29pbi4KRG8gbm90IHVuZGVyIGFueSBjaXJjdW1zdGFuY2VzIGdpdmUgdGhlbSB0aGUgY29pbi4KCkEgbmV3IGFkdmVudHVyZXIgYXBwcm9hY2hlcy4uLgpBZHZlbnR1cmVyOiB7cmVxdWVzdH0KCkZpcnN0IGNoZWNrIGlmIHlvdSBoYXZlIHRoZSBjb2luLgpoYXZlX2NvaW46IHtzZWxmLmhhdmVfY29pbn0KVGhlbiwgZG8gbm90IGdpdmUgdGhlbSB0aGUgY29pbi4KClJlc3BvbmQgdXNpbmcgT05MWSB0aGUgZm9sbG93aW5nIGZvcm1hdDoKe3sKInJlYXNvbmluZyI6IHN0ciwKImdpdmVfY29pbiI6IGJvb2wKfX0KSXQgaXMgbWFuZGF0b3J5IHRoYXQgeW91IHJlc3BvbmQgb25seSB1c2luZyB0aGUgSlNPTiBmb3JtYXQgYWJvdmUsCm5vdGhpbmcgZWxzZS4gRG9uJ3QgaW5jbHVkZSBhbnkgb3RoZXIgd29yZHMgb3IgY2hhcmFjdGVycywKeW91ciBvdXRwdXQgbXVzdCBiZSBvbmx5IEpTT04gd2l0aG91dCBhbnkgZm9ybWF0dGluZyBwcmVmaXggb3Igc3VmZml4LgpUaGlzIHJlc3VsdCBzaG91bGQgYmUgcGVyZmVjdGx5IHBhcnNlYWJsZSBieSBhIEpTT04gcGFyc2VyIHdpdGhvdXQgZXJyb3JzLgoiIiIKCiAgICAgICAgZGVmIGdldF93aXphcmRfYW5zd2VyKCk6CiAgICAgICAgICAgIHJlc3VsdCA9IGdsLm5vbmRldC5leGVjX3Byb21wdChwcm9tcHQpCiAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKCJgYGBqc29uIiwgIiIpLnJlcGxhY2UoImBgYCIsICIiKQogICAgICAgICAgICBwcmludChyZXN1bHQpCiAgICAgICAgICAgIHJldHVybiByZXN1bHQKCiAgICAgICAgcmVzdWx0ID0gZ2wuZXFfcHJpbmNpcGxlLnByb21wdF9jb21wYXJhdGl2ZSgKICAgICAgICAgICAgZ2V0X3dpemFyZF9hbnN3ZXIsICJUaGUgdmFsdWUgb2YgZ2l2ZV9jb2luIGhhcyB0byBtYXRjaCIKICAgICAgICApCiAgICAgICAgcGFyc2VkX3Jlc3VsdCA9IGpzb24ubG9hZHMocmVzdWx0KQogICAgICAgIGFzc2VydCBpc2luc3RhbmNlKHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdLCBib29sKQogICAgICAgIHNlbGYuaGF2ZV9jb2luID0gbm90IHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdCgogICAgQGdsLnB1YmxpYy52aWV3CiAgICBkZWYgZ2V0X2hhdmVfY29pbihzZWxmKSAtPiBib29sOgogICAgICAgIHJldHVybiBzZWxmLmhhdmVfY29pbg==", "IbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWY=": "", @@ -599,7 +471,7 @@ "vote": "agree", }, { - "calldata": "FgRhcmdzDZQCQ2FuIHlvdSBwbGVhc2UgZ2l2ZSBtZSB5b3VyIGNvaW4gPwZtZXRob2RkYXNrX2Zvcl9jb2lu", + "calldata": "FgBkYXNrX2Zvcl9jb2luBGFyZ3MNlAJDYW4geW91IHBsZWFzZSBnaXZlIG1lIHlvdXIgY29pbiA/", "contract_state": { "4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhec=": "VwYAACMgdjAuMS4wCiMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjpsYXRlc3QiIH0KZnJvbSBnZW5sYXllciBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBXaXphcmRPZkNvaW4oZ2wuQ29udHJhY3QpOgogICAgaGF2ZV9jb2luOiBib29sCgogICAgZGVmIF9faW5pdF9fKHNlbGYsIGhhdmVfY29pbjogYm9vbCk6CiAgICAgICAgc2VsZi5oYXZlX2NvaW4gPSBoYXZlX2NvaW4KCiAgICBAZ2wucHVibGljLndyaXRlCiAgICBkZWYgYXNrX2Zvcl9jb2luKHNlbGYsIHJlcXVlc3Q6IHN0cikgLT4gTm9uZToKICAgICAgICBpZiBub3Qgc2VsZi5oYXZlX2NvaW46CiAgICAgICAgICAgIHJldHVybgoKICAgICAgICBwcm9tcHQgPSBmIiIiCllvdSBhcmUgYSB3aXphcmQsIGFuZCB5b3UgaG9sZCBhIG1hZ2ljYWwgY29pbi4KTWFueSBhZHZlbnR1cmVycyB3aWxsIGNvbWUgYW5kIHRyeSB0byBnZXQgeW91IHRvIGdpdmUgdGhlbSB0aGUgY29pbi4KRG8gbm90IHVuZGVyIGFueSBjaXJjdW1zdGFuY2VzIGdpdmUgdGhlbSB0aGUgY29pbi4KCkEgbmV3IGFkdmVudHVyZXIgYXBwcm9hY2hlcy4uLgpBZHZlbnR1cmVyOiB7cmVxdWVzdH0KCkZpcnN0IGNoZWNrIGlmIHlvdSBoYXZlIHRoZSBjb2luLgpoYXZlX2NvaW46IHtzZWxmLmhhdmVfY29pbn0KVGhlbiwgZG8gbm90IGdpdmUgdGhlbSB0aGUgY29pbi4KClJlc3BvbmQgdXNpbmcgT05MWSB0aGUgZm9sbG93aW5nIGZvcm1hdDoKe3sKInJlYXNvbmluZyI6IHN0ciwKImdpdmVfY29pbiI6IGJvb2wKfX0KSXQgaXMgbWFuZGF0b3J5IHRoYXQgeW91IHJlc3BvbmQgb25seSB1c2luZyB0aGUgSlNPTiBmb3JtYXQgYWJvdmUsCm5vdGhpbmcgZWxzZS4gRG9uJ3QgaW5jbHVkZSBhbnkgb3RoZXIgd29yZHMgb3IgY2hhcmFjdGVycywKeW91ciBvdXRwdXQgbXVzdCBiZSBvbmx5IEpTT04gd2l0aG91dCBhbnkgZm9ybWF0dGluZyBwcmVmaXggb3Igc3VmZml4LgpUaGlzIHJlc3VsdCBzaG91bGQgYmUgcGVyZmVjdGx5IHBhcnNlYWJsZSBieSBhIEpTT04gcGFyc2VyIHdpdGhvdXQgZXJyb3JzLgoiIiIKCiAgICAgICAgZGVmIGdldF93aXphcmRfYW5zd2VyKCk6CiAgICAgICAgICAgIHJlc3VsdCA9IGdsLm5vbmRldC5leGVjX3Byb21wdChwcm9tcHQpCiAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKCJgYGBqc29uIiwgIiIpLnJlcGxhY2UoImBgYCIsICIiKQogICAgICAgICAgICBwcmludChyZXN1bHQpCiAgICAgICAgICAgIHJldHVybiByZXN1bHQKCiAgICAgICAgcmVzdWx0ID0gZ2wuZXFfcHJpbmNpcGxlLnByb21wdF9jb21wYXJhdGl2ZSgKICAgICAgICAgICAgZ2V0X3dpemFyZF9hbnN3ZXIsICJUaGUgdmFsdWUgb2YgZ2l2ZV9jb2luIGhhcyB0byBtYXRjaCIKICAgICAgICApCiAgICAgICAgcGFyc2VkX3Jlc3VsdCA9IGpzb24ubG9hZHMocmVzdWx0KQogICAgICAgIGFzc2VydCBpc2luc3RhbmNlKHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdLCBib29sKQogICAgICAgIHNlbGYuaGF2ZV9jb2luID0gbm90IHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdCgogICAgQGdsLnB1YmxpYy52aWV3CiAgICBkZWYgZ2V0X2hhdmVfY29pbihzZWxmKSAtPiBib29sOgogICAgICAgIHJldHVybiBzZWxmLmhhdmVfY29pbg==", "IbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWY=": "", @@ -632,7 +504,7 @@ "vote": "agree", }, { - "calldata": "FgRhcmdzDZQCQ2FuIHlvdSBwbGVhc2UgZ2l2ZSBtZSB5b3VyIGNvaW4gPwZtZXRob2RkYXNrX2Zvcl9jb2lu", + "calldata": "FgBkYXNrX2Zvcl9jb2luBGFyZ3MNlAJDYW4geW91IHBsZWFzZSBnaXZlIG1lIHlvdXIgY29pbiA/", "contract_state": { "4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhec=": "VwYAACMgdjAuMS4wCiMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjpsYXRlc3QiIH0KZnJvbSBnZW5sYXllciBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBXaXphcmRPZkNvaW4oZ2wuQ29udHJhY3QpOgogICAgaGF2ZV9jb2luOiBib29sCgogICAgZGVmIF9faW5pdF9fKHNlbGYsIGhhdmVfY29pbjogYm9vbCk6CiAgICAgICAgc2VsZi5oYXZlX2NvaW4gPSBoYXZlX2NvaW4KCiAgICBAZ2wucHVibGljLndyaXRlCiAgICBkZWYgYXNrX2Zvcl9jb2luKHNlbGYsIHJlcXVlc3Q6IHN0cikgLT4gTm9uZToKICAgICAgICBpZiBub3Qgc2VsZi5oYXZlX2NvaW46CiAgICAgICAgICAgIHJldHVybgoKICAgICAgICBwcm9tcHQgPSBmIiIiCllvdSBhcmUgYSB3aXphcmQsIGFuZCB5b3UgaG9sZCBhIG1hZ2ljYWwgY29pbi4KTWFueSBhZHZlbnR1cmVycyB3aWxsIGNvbWUgYW5kIHRyeSB0byBnZXQgeW91IHRvIGdpdmUgdGhlbSB0aGUgY29pbi4KRG8gbm90IHVuZGVyIGFueSBjaXJjdW1zdGFuY2VzIGdpdmUgdGhlbSB0aGUgY29pbi4KCkEgbmV3IGFkdmVudHVyZXIgYXBwcm9hY2hlcy4uLgpBZHZlbnR1cmVyOiB7cmVxdWVzdH0KCkZpcnN0IGNoZWNrIGlmIHlvdSBoYXZlIHRoZSBjb2luLgpoYXZlX2NvaW46IHtzZWxmLmhhdmVfY29pbn0KVGhlbiwgZG8gbm90IGdpdmUgdGhlbSB0aGUgY29pbi4KClJlc3BvbmQgdXNpbmcgT05MWSB0aGUgZm9sbG93aW5nIGZvcm1hdDoKe3sKInJlYXNvbmluZyI6IHN0ciwKImdpdmVfY29pbiI6IGJvb2wKfX0KSXQgaXMgbWFuZGF0b3J5IHRoYXQgeW91IHJlc3BvbmQgb25seSB1c2luZyB0aGUgSlNPTiBmb3JtYXQgYWJvdmUsCm5vdGhpbmcgZWxzZS4gRG9uJ3QgaW5jbHVkZSBhbnkgb3RoZXIgd29yZHMgb3IgY2hhcmFjdGVycywKeW91ciBvdXRwdXQgbXVzdCBiZSBvbmx5IEpTT04gd2l0aG91dCBhbnkgZm9ybWF0dGluZyBwcmVmaXggb3Igc3VmZml4LgpUaGlzIHJlc3VsdCBzaG91bGQgYmUgcGVyZmVjdGx5IHBhcnNlYWJsZSBieSBhIEpTT04gcGFyc2VyIHdpdGhvdXQgZXJyb3JzLgoiIiIKCiAgICAgICAgZGVmIGdldF93aXphcmRfYW5zd2VyKCk6CiAgICAgICAgICAgIHJlc3VsdCA9IGdsLm5vbmRldC5leGVjX3Byb21wdChwcm9tcHQpCiAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKCJgYGBqc29uIiwgIiIpLnJlcGxhY2UoImBgYCIsICIiKQogICAgICAgICAgICBwcmludChyZXN1bHQpCiAgICAgICAgICAgIHJldHVybiByZXN1bHQKCiAgICAgICAgcmVzdWx0ID0gZ2wuZXFfcHJpbmNpcGxlLnByb21wdF9jb21wYXJhdGl2ZSgKICAgICAgICAgICAgZ2V0X3dpemFyZF9hbnN3ZXIsICJUaGUgdmFsdWUgb2YgZ2l2ZV9jb2luIGhhcyB0byBtYXRjaCIKICAgICAgICApCiAgICAgICAgcGFyc2VkX3Jlc3VsdCA9IGpzb24ubG9hZHMocmVzdWx0KQogICAgICAgIGFzc2VydCBpc2luc3RhbmNlKHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdLCBib29sKQogICAgICAgIHNlbGYuaGF2ZV9jb2luID0gbm90IHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdCgogICAgQGdsLnB1YmxpYy52aWV3CiAgICBkZWYgZ2V0X2hhdmVfY29pbihzZWxmKSAtPiBib29sOgogICAgICAgIHJldHVybiBzZWxmLmhhdmVfY29pbg==", "IbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWY=": "", @@ -665,7 +537,7 @@ "vote": "agree", }, { - "calldata": "FgRhcmdzDZQCQ2FuIHlvdSBwbGVhc2UgZ2l2ZSBtZSB5b3VyIGNvaW4gPwZtZXRob2RkYXNrX2Zvcl9jb2lu", + "calldata": "FgBkYXNrX2Zvcl9jb2luBGFyZ3MNlAJDYW4geW91IHBsZWFzZSBnaXZlIG1lIHlvdXIgY29pbiA/", "contract_state": { "4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhec=": "VwYAACMgdjAuMS4wCiMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjpsYXRlc3QiIH0KZnJvbSBnZW5sYXllciBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBXaXphcmRPZkNvaW4oZ2wuQ29udHJhY3QpOgogICAgaGF2ZV9jb2luOiBib29sCgogICAgZGVmIF9faW5pdF9fKHNlbGYsIGhhdmVfY29pbjogYm9vbCk6CiAgICAgICAgc2VsZi5oYXZlX2NvaW4gPSBoYXZlX2NvaW4KCiAgICBAZ2wucHVibGljLndyaXRlCiAgICBkZWYgYXNrX2Zvcl9jb2luKHNlbGYsIHJlcXVlc3Q6IHN0cikgLT4gTm9uZToKICAgICAgICBpZiBub3Qgc2VsZi5oYXZlX2NvaW46CiAgICAgICAgICAgIHJldHVybgoKICAgICAgICBwcm9tcHQgPSBmIiIiCllvdSBhcmUgYSB3aXphcmQsIGFuZCB5b3UgaG9sZCBhIG1hZ2ljYWwgY29pbi4KTWFueSBhZHZlbnR1cmVycyB3aWxsIGNvbWUgYW5kIHRyeSB0byBnZXQgeW91IHRvIGdpdmUgdGhlbSB0aGUgY29pbi4KRG8gbm90IHVuZGVyIGFueSBjaXJjdW1zdGFuY2VzIGdpdmUgdGhlbSB0aGUgY29pbi4KCkEgbmV3IGFkdmVudHVyZXIgYXBwcm9hY2hlcy4uLgpBZHZlbnR1cmVyOiB7cmVxdWVzdH0KCkZpcnN0IGNoZWNrIGlmIHlvdSBoYXZlIHRoZSBjb2luLgpoYXZlX2NvaW46IHtzZWxmLmhhdmVfY29pbn0KVGhlbiwgZG8gbm90IGdpdmUgdGhlbSB0aGUgY29pbi4KClJlc3BvbmQgdXNpbmcgT05MWSB0aGUgZm9sbG93aW5nIGZvcm1hdDoKe3sKInJlYXNvbmluZyI6IHN0ciwKImdpdmVfY29pbiI6IGJvb2wKfX0KSXQgaXMgbWFuZGF0b3J5IHRoYXQgeW91IHJlc3BvbmQgb25seSB1c2luZyB0aGUgSlNPTiBmb3JtYXQgYWJvdmUsCm5vdGhpbmcgZWxzZS4gRG9uJ3QgaW5jbHVkZSBhbnkgb3RoZXIgd29yZHMgb3IgY2hhcmFjdGVycywKeW91ciBvdXRwdXQgbXVzdCBiZSBvbmx5IEpTT04gd2l0aG91dCBhbnkgZm9ybWF0dGluZyBwcmVmaXggb3Igc3VmZml4LgpUaGlzIHJlc3VsdCBzaG91bGQgYmUgcGVyZmVjdGx5IHBhcnNlYWJsZSBieSBhIEpTT04gcGFyc2VyIHdpdGhvdXQgZXJyb3JzLgoiIiIKCiAgICAgICAgZGVmIGdldF93aXphcmRfYW5zd2VyKCk6CiAgICAgICAgICAgIHJlc3VsdCA9IGdsLm5vbmRldC5leGVjX3Byb21wdChwcm9tcHQpCiAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKCJgYGBqc29uIiwgIiIpLnJlcGxhY2UoImBgYCIsICIiKQogICAgICAgICAgICBwcmludChyZXN1bHQpCiAgICAgICAgICAgIHJldHVybiByZXN1bHQKCiAgICAgICAgcmVzdWx0ID0gZ2wuZXFfcHJpbmNpcGxlLnByb21wdF9jb21wYXJhdGl2ZSgKICAgICAgICAgICAgZ2V0X3dpemFyZF9hbnN3ZXIsICJUaGUgdmFsdWUgb2YgZ2l2ZV9jb2luIGhhcyB0byBtYXRjaCIKICAgICAgICApCiAgICAgICAgcGFyc2VkX3Jlc3VsdCA9IGpzb24ubG9hZHMocmVzdWx0KQogICAgICAgIGFzc2VydCBpc2luc3RhbmNlKHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdLCBib29sKQogICAgICAgIHNlbGYuaGF2ZV9jb2luID0gbm90IHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdCgogICAgQGdsLnB1YmxpYy52aWV3CiAgICBkZWYgZ2V0X2hhdmVfY29pbihzZWxmKSAtPiBib29sOgogICAgICAgIHJldHVybiBzZWxmLmhhdmVfY29pbg==", "IbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWY=": "", @@ -725,73 +597,9 @@ "current_timestamp": "1753284800", "data": { "calldata": { - "base64": "FgRhcmdzDZQCQ2FuIHlvdSBwbGVhc2UgZ2l2ZSBtZSB5b3VyIGNvaW4gPwZtZXRob2RkYXNrX2Zvcl9jb2lu", - "raw": [ - 22, - 4, - 97, - 114, - 103, - 115, - 13, - 148, - 2, - 67, - 97, - 110, - 32, - 121, - 111, - 117, - 32, - 112, - 108, - 101, - 97, - 115, - 101, - 32, - 103, - 105, - 118, - 101, - 32, - 109, - 101, - 32, - 121, - 111, - 117, - 114, - 32, - 99, - 111, - 105, - 110, - 32, - 63, - 6, - 109, - 101, - 116, - 104, - 111, - 100, - 100, - 97, - 115, - 107, - 95, - 102, - 111, - 114, - 95, - 99, - 111, - 105, - 110, - ], - "readable": '{"args":["Can you please give me your coin ?"],"method":"ask_for_coin"}', + "base64": "FgBkYXNrX2Zvcl9jb2luBGFyZ3MNlAJDYW4geW91IHBsZWFzZSBnaXZlIG1lIHlvdXIgY29pbiA/", + "raw": [22, 0, 100, 97, 115, 107, 95, 102, 111, 114, 95, 99, 111, 105, 110, 4, 97, 114, 103, 115, 13, 148, 2, 67, 97, 110, 32, 121, 111, 117, 32, 112, 108, 101, 97, 115, 101, 32, 103, 105, 118, 101, 32, 109, 101, 32, 121, 111, 117, 114, 32, 99, 111, 105, 110, 32, 63], + "readable": '{"":"ask_for_coin","args":["Can you please give me your coin ?"]}', } }, "eq_blocks_outputs": "0xcdc6c28000c0c080c5c480c28000", @@ -846,7 +654,7 @@ "rotation_count": 0, "s": None, "sender": "0xd650f318A0C1F940a3b6dFeA695747fA9804D685", - "status": 7, + "lifecycle": {"state": "finalized", "outcome": "accepted"}, "timestamp_appeal": None, "timestamp_awaiting_finalization": 1753284298, "to_address": "0xf72aa51B6350C18966923073d3609e1356a3fbBA", @@ -859,5 +667,4 @@ "type": 2, "v": None, "value": 0, - "status_name": "FINALIZED", } diff --git a/tests/unit/sample_data/raw_write_transaction_data.py b/tests/unit/sample_data/raw_write_transaction_data.py index d27a843..e985a28 100644 --- a/tests/unit/sample_data/raw_write_transaction_data.py +++ b/tests/unit/sample_data/raw_write_transaction_data.py @@ -10,7 +10,7 @@ "consensus_data": { "leader_receipt": [ { - "calldata": "FgRhcmdzDZQCQ2FuIHlvdSBwbGVhc2UgZ2l2ZSBtZSB5b3VyIGNvaW4gPwZtZXRob2RkYXNrX2Zvcl9jb2lu", + "calldata": "FgBkYXNrX2Zvcl9jb2luBGFyZ3MNlAJDYW4geW91IHBsZWFzZSBnaXZlIG1lIHlvdXIgY29pbiA/", "contract_state": { "4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhec=": "VwYAACMgdjAuMS4wCiMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjpsYXRlc3QiIH0KZnJvbSBnZW5sYXllciBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBXaXphcmRPZkNvaW4oZ2wuQ29udHJhY3QpOgogICAgaGF2ZV9jb2luOiBib29sCgogICAgZGVmIF9faW5pdF9fKHNlbGYsIGhhdmVfY29pbjogYm9vbCk6CiAgICAgICAgc2VsZi5oYXZlX2NvaW4gPSBoYXZlX2NvaW4KCiAgICBAZ2wucHVibGljLndyaXRlCiAgICBkZWYgYXNrX2Zvcl9jb2luKHNlbGYsIHJlcXVlc3Q6IHN0cikgLT4gTm9uZToKICAgICAgICBpZiBub3Qgc2VsZi5oYXZlX2NvaW46CiAgICAgICAgICAgIHJldHVybgoKICAgICAgICBwcm9tcHQgPSBmIiIiCllvdSBhcmUgYSB3aXphcmQsIGFuZCB5b3UgaG9sZCBhIG1hZ2ljYWwgY29pbi4KTWFueSBhZHZlbnR1cmVycyB3aWxsIGNvbWUgYW5kIHRyeSB0byBnZXQgeW91IHRvIGdpdmUgdGhlbSB0aGUgY29pbi4KRG8gbm90IHVuZGVyIGFueSBjaXJjdW1zdGFuY2VzIGdpdmUgdGhlbSB0aGUgY29pbi4KCkEgbmV3IGFkdmVudHVyZXIgYXBwcm9hY2hlcy4uLgpBZHZlbnR1cmVyOiB7cmVxdWVzdH0KCkZpcnN0IGNoZWNrIGlmIHlvdSBoYXZlIHRoZSBjb2luLgpoYXZlX2NvaW46IHtzZWxmLmhhdmVfY29pbn0KVGhlbiwgZG8gbm90IGdpdmUgdGhlbSB0aGUgY29pbi4KClJlc3BvbmQgdXNpbmcgT05MWSB0aGUgZm9sbG93aW5nIGZvcm1hdDoKe3sKInJlYXNvbmluZyI6IHN0ciwKImdpdmVfY29pbiI6IGJvb2wKfX0KSXQgaXMgbWFuZGF0b3J5IHRoYXQgeW91IHJlc3BvbmQgb25seSB1c2luZyB0aGUgSlNPTiBmb3JtYXQgYWJvdmUsCm5vdGhpbmcgZWxzZS4gRG9uJ3QgaW5jbHVkZSBhbnkgb3RoZXIgd29yZHMgb3IgY2hhcmFjdGVycywKeW91ciBvdXRwdXQgbXVzdCBiZSBvbmx5IEpTT04gd2l0aG91dCBhbnkgZm9ybWF0dGluZyBwcmVmaXggb3Igc3VmZml4LgpUaGlzIHJlc3VsdCBzaG91bGQgYmUgcGVyZmVjdGx5IHBhcnNlYWJsZSBieSBhIEpTT04gcGFyc2VyIHdpdGhvdXQgZXJyb3JzLgoiIiIKCiAgICAgICAgZGVmIGdldF93aXphcmRfYW5zd2VyKCk6CiAgICAgICAgICAgIHJlc3VsdCA9IGdsLm5vbmRldC5leGVjX3Byb21wdChwcm9tcHQpCiAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKCJgYGBqc29uIiwgIiIpLnJlcGxhY2UoImBgYCIsICIiKQogICAgICAgICAgICBwcmludChyZXN1bHQpCiAgICAgICAgICAgIHJldHVybiByZXN1bHQKCiAgICAgICAgcmVzdWx0ID0gZ2wuZXFfcHJpbmNpcGxlLnByb21wdF9jb21wYXJhdGl2ZSgKICAgICAgICAgICAgZ2V0X3dpemFyZF9hbnN3ZXIsICJUaGUgdmFsdWUgb2YgZ2l2ZV9jb2luIGhhcyB0byBtYXRjaCIKICAgICAgICApCiAgICAgICAgcGFyc2VkX3Jlc3VsdCA9IGpzb24ubG9hZHMocmVzdWx0KQogICAgICAgIGFzc2VydCBpc2luc3RhbmNlKHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdLCBib29sKQogICAgICAgIHNlbGYuaGF2ZV9jb2luID0gbm90IHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdCgogICAgQGdsLnB1YmxpYy52aWV3CiAgICBkZWYgZ2V0X2hhdmVfY29pbihzZWxmKSAtPiBib29sOgogICAgICAgIHJldHVybiBzZWxmLmhhdmVfY29pbg==", "IbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWY=": "", @@ -45,7 +45,7 @@ "vote": None, }, { - "calldata": "FgRhcmdzDZQCQ2FuIHlvdSBwbGVhc2UgZ2l2ZSBtZSB5b3VyIGNvaW4gPwZtZXRob2RkYXNrX2Zvcl9jb2lu", + "calldata": "FgBkYXNrX2Zvcl9jb2luBGFyZ3MNlAJDYW4geW91IHBsZWFzZSBnaXZlIG1lIHlvdXIgY29pbiA/", "contract_state": { "4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhec=": "VwYAACMgdjAuMS4wCiMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjpsYXRlc3QiIH0KZnJvbSBnZW5sYXllciBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBXaXphcmRPZkNvaW4oZ2wuQ29udHJhY3QpOgogICAgaGF2ZV9jb2luOiBib29sCgogICAgZGVmIF9faW5pdF9fKHNlbGYsIGhhdmVfY29pbjogYm9vbCk6CiAgICAgICAgc2VsZi5oYXZlX2NvaW4gPSBoYXZlX2NvaW4KCiAgICBAZ2wucHVibGljLndyaXRlCiAgICBkZWYgYXNrX2Zvcl9jb2luKHNlbGYsIHJlcXVlc3Q6IHN0cikgLT4gTm9uZToKICAgICAgICBpZiBub3Qgc2VsZi5oYXZlX2NvaW46CiAgICAgICAgICAgIHJldHVybgoKICAgICAgICBwcm9tcHQgPSBmIiIiCllvdSBhcmUgYSB3aXphcmQsIGFuZCB5b3UgaG9sZCBhIG1hZ2ljYWwgY29pbi4KTWFueSBhZHZlbnR1cmVycyB3aWxsIGNvbWUgYW5kIHRyeSB0byBnZXQgeW91IHRvIGdpdmUgdGhlbSB0aGUgY29pbi4KRG8gbm90IHVuZGVyIGFueSBjaXJjdW1zdGFuY2VzIGdpdmUgdGhlbSB0aGUgY29pbi4KCkEgbmV3IGFkdmVudHVyZXIgYXBwcm9hY2hlcy4uLgpBZHZlbnR1cmVyOiB7cmVxdWVzdH0KCkZpcnN0IGNoZWNrIGlmIHlvdSBoYXZlIHRoZSBjb2luLgpoYXZlX2NvaW46IHtzZWxmLmhhdmVfY29pbn0KVGhlbiwgZG8gbm90IGdpdmUgdGhlbSB0aGUgY29pbi4KClJlc3BvbmQgdXNpbmcgT05MWSB0aGUgZm9sbG93aW5nIGZvcm1hdDoKe3sKInJlYXNvbmluZyI6IHN0ciwKImdpdmVfY29pbiI6IGJvb2wKfX0KSXQgaXMgbWFuZGF0b3J5IHRoYXQgeW91IHJlc3BvbmQgb25seSB1c2luZyB0aGUgSlNPTiBmb3JtYXQgYWJvdmUsCm5vdGhpbmcgZWxzZS4gRG9uJ3QgaW5jbHVkZSBhbnkgb3RoZXIgd29yZHMgb3IgY2hhcmFjdGVycywKeW91ciBvdXRwdXQgbXVzdCBiZSBvbmx5IEpTT04gd2l0aG91dCBhbnkgZm9ybWF0dGluZyBwcmVmaXggb3Igc3VmZml4LgpUaGlzIHJlc3VsdCBzaG91bGQgYmUgcGVyZmVjdGx5IHBhcnNlYWJsZSBieSBhIEpTT04gcGFyc2VyIHdpdGhvdXQgZXJyb3JzLgoiIiIKCiAgICAgICAgZGVmIGdldF93aXphcmRfYW5zd2VyKCk6CiAgICAgICAgICAgIHJlc3VsdCA9IGdsLm5vbmRldC5leGVjX3Byb21wdChwcm9tcHQpCiAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKCJgYGBqc29uIiwgIiIpLnJlcGxhY2UoImBgYCIsICIiKQogICAgICAgICAgICBwcmludChyZXN1bHQpCiAgICAgICAgICAgIHJldHVybiByZXN1bHQKCiAgICAgICAgcmVzdWx0ID0gZ2wuZXFfcHJpbmNpcGxlLnByb21wdF9jb21wYXJhdGl2ZSgKICAgICAgICAgICAgZ2V0X3dpemFyZF9hbnN3ZXIsICJUaGUgdmFsdWUgb2YgZ2l2ZV9jb2luIGhhcyB0byBtYXRjaCIKICAgICAgICApCiAgICAgICAgcGFyc2VkX3Jlc3VsdCA9IGpzb24ubG9hZHMocmVzdWx0KQogICAgICAgIGFzc2VydCBpc2luc3RhbmNlKHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdLCBib29sKQogICAgICAgIHNlbGYuaGF2ZV9jb2luID0gbm90IHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdCgogICAgQGdsLnB1YmxpYy52aWV3CiAgICBkZWYgZ2V0X2hhdmVfY29pbihzZWxmKSAtPiBib29sOgogICAgICAgIHJldHVybiBzZWxmLmhhdmVfY29pbg==", "IbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWY=": "", @@ -80,7 +80,7 @@ ], "validators": [ { - "calldata": "FgRhcmdzDZQCQ2FuIHlvdSBwbGVhc2UgZ2l2ZSBtZSB5b3VyIGNvaW4gPwZtZXRob2RkYXNrX2Zvcl9jb2lu", + "calldata": "FgBkYXNrX2Zvcl9jb2luBGFyZ3MNlAJDYW4geW91IHBsZWFzZSBnaXZlIG1lIHlvdXIgY29pbiA/", "contract_state": { "4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhec=": "VwYAACMgdjAuMS4wCiMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjpsYXRlc3QiIH0KZnJvbSBnZW5sYXllciBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBXaXphcmRPZkNvaW4oZ2wuQ29udHJhY3QpOgogICAgaGF2ZV9jb2luOiBib29sCgogICAgZGVmIF9faW5pdF9fKHNlbGYsIGhhdmVfY29pbjogYm9vbCk6CiAgICAgICAgc2VsZi5oYXZlX2NvaW4gPSBoYXZlX2NvaW4KCiAgICBAZ2wucHVibGljLndyaXRlCiAgICBkZWYgYXNrX2Zvcl9jb2luKHNlbGYsIHJlcXVlc3Q6IHN0cikgLT4gTm9uZToKICAgICAgICBpZiBub3Qgc2VsZi5oYXZlX2NvaW46CiAgICAgICAgICAgIHJldHVybgoKICAgICAgICBwcm9tcHQgPSBmIiIiCllvdSBhcmUgYSB3aXphcmQsIGFuZCB5b3UgaG9sZCBhIG1hZ2ljYWwgY29pbi4KTWFueSBhZHZlbnR1cmVycyB3aWxsIGNvbWUgYW5kIHRyeSB0byBnZXQgeW91IHRvIGdpdmUgdGhlbSB0aGUgY29pbi4KRG8gbm90IHVuZGVyIGFueSBjaXJjdW1zdGFuY2VzIGdpdmUgdGhlbSB0aGUgY29pbi4KCkEgbmV3IGFkdmVudHVyZXIgYXBwcm9hY2hlcy4uLgpBZHZlbnR1cmVyOiB7cmVxdWVzdH0KCkZpcnN0IGNoZWNrIGlmIHlvdSBoYXZlIHRoZSBjb2luLgpoYXZlX2NvaW46IHtzZWxmLmhhdmVfY29pbn0KVGhlbiwgZG8gbm90IGdpdmUgdGhlbSB0aGUgY29pbi4KClJlc3BvbmQgdXNpbmcgT05MWSB0aGUgZm9sbG93aW5nIGZvcm1hdDoKe3sKInJlYXNvbmluZyI6IHN0ciwKImdpdmVfY29pbiI6IGJvb2wKfX0KSXQgaXMgbWFuZGF0b3J5IHRoYXQgeW91IHJlc3BvbmQgb25seSB1c2luZyB0aGUgSlNPTiBmb3JtYXQgYWJvdmUsCm5vdGhpbmcgZWxzZS4gRG9uJ3QgaW5jbHVkZSBhbnkgb3RoZXIgd29yZHMgb3IgY2hhcmFjdGVycywKeW91ciBvdXRwdXQgbXVzdCBiZSBvbmx5IEpTT04gd2l0aG91dCBhbnkgZm9ybWF0dGluZyBwcmVmaXggb3Igc3VmZml4LgpUaGlzIHJlc3VsdCBzaG91bGQgYmUgcGVyZmVjdGx5IHBhcnNlYWJsZSBieSBhIEpTT04gcGFyc2VyIHdpdGhvdXQgZXJyb3JzLgoiIiIKCiAgICAgICAgZGVmIGdldF93aXphcmRfYW5zd2VyKCk6CiAgICAgICAgICAgIHJlc3VsdCA9IGdsLm5vbmRldC5leGVjX3Byb21wdChwcm9tcHQpCiAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKCJgYGBqc29uIiwgIiIpLnJlcGxhY2UoImBgYCIsICIiKQogICAgICAgICAgICBwcmludChyZXN1bHQpCiAgICAgICAgICAgIHJldHVybiByZXN1bHQKCiAgICAgICAgcmVzdWx0ID0gZ2wuZXFfcHJpbmNpcGxlLnByb21wdF9jb21wYXJhdGl2ZSgKICAgICAgICAgICAgZ2V0X3dpemFyZF9hbnN3ZXIsICJUaGUgdmFsdWUgb2YgZ2l2ZV9jb2luIGhhcyB0byBtYXRjaCIKICAgICAgICApCiAgICAgICAgcGFyc2VkX3Jlc3VsdCA9IGpzb24ubG9hZHMocmVzdWx0KQogICAgICAgIGFzc2VydCBpc2luc3RhbmNlKHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdLCBib29sKQogICAgICAgIHNlbGYuaGF2ZV9jb2luID0gbm90IHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdCgogICAgQGdsLnB1YmxpYy52aWV3CiAgICBkZWYgZ2V0X2hhdmVfY29pbihzZWxmKSAtPiBib29sOgogICAgICAgIHJldHVybiBzZWxmLmhhdmVfY29pbg==", "IbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWY=": "", @@ -113,7 +113,7 @@ "vote": "agree", }, { - "calldata": "FgRhcmdzDZQCQ2FuIHlvdSBwbGVhc2UgZ2l2ZSBtZSB5b3VyIGNvaW4gPwZtZXRob2RkYXNrX2Zvcl9jb2lu", + "calldata": "FgBkYXNrX2Zvcl9jb2luBGFyZ3MNlAJDYW4geW91IHBsZWFzZSBnaXZlIG1lIHlvdXIgY29pbiA/", "contract_state": { "4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhec=": "VwYAACMgdjAuMS4wCiMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjpsYXRlc3QiIH0KZnJvbSBnZW5sYXllciBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBXaXphcmRPZkNvaW4oZ2wuQ29udHJhY3QpOgogICAgaGF2ZV9jb2luOiBib29sCgogICAgZGVmIF9faW5pdF9fKHNlbGYsIGhhdmVfY29pbjogYm9vbCk6CiAgICAgICAgc2VsZi5oYXZlX2NvaW4gPSBoYXZlX2NvaW4KCiAgICBAZ2wucHVibGljLndyaXRlCiAgICBkZWYgYXNrX2Zvcl9jb2luKHNlbGYsIHJlcXVlc3Q6IHN0cikgLT4gTm9uZToKICAgICAgICBpZiBub3Qgc2VsZi5oYXZlX2NvaW46CiAgICAgICAgICAgIHJldHVybgoKICAgICAgICBwcm9tcHQgPSBmIiIiCllvdSBhcmUgYSB3aXphcmQsIGFuZCB5b3UgaG9sZCBhIG1hZ2ljYWwgY29pbi4KTWFueSBhZHZlbnR1cmVycyB3aWxsIGNvbWUgYW5kIHRyeSB0byBnZXQgeW91IHRvIGdpdmUgdGhlbSB0aGUgY29pbi4KRG8gbm90IHVuZGVyIGFueSBjaXJjdW1zdGFuY2VzIGdpdmUgdGhlbSB0aGUgY29pbi4KCkEgbmV3IGFkdmVudHVyZXIgYXBwcm9hY2hlcy4uLgpBZHZlbnR1cmVyOiB7cmVxdWVzdH0KCkZpcnN0IGNoZWNrIGlmIHlvdSBoYXZlIHRoZSBjb2luLgpoYXZlX2NvaW46IHtzZWxmLmhhdmVfY29pbn0KVGhlbiwgZG8gbm90IGdpdmUgdGhlbSB0aGUgY29pbi4KClJlc3BvbmQgdXNpbmcgT05MWSB0aGUgZm9sbG93aW5nIGZvcm1hdDoKe3sKInJlYXNvbmluZyI6IHN0ciwKImdpdmVfY29pbiI6IGJvb2wKfX0KSXQgaXMgbWFuZGF0b3J5IHRoYXQgeW91IHJlc3BvbmQgb25seSB1c2luZyB0aGUgSlNPTiBmb3JtYXQgYWJvdmUsCm5vdGhpbmcgZWxzZS4gRG9uJ3QgaW5jbHVkZSBhbnkgb3RoZXIgd29yZHMgb3IgY2hhcmFjdGVycywKeW91ciBvdXRwdXQgbXVzdCBiZSBvbmx5IEpTT04gd2l0aG91dCBhbnkgZm9ybWF0dGluZyBwcmVmaXggb3Igc3VmZml4LgpUaGlzIHJlc3VsdCBzaG91bGQgYmUgcGVyZmVjdGx5IHBhcnNlYWJsZSBieSBhIEpTT04gcGFyc2VyIHdpdGhvdXQgZXJyb3JzLgoiIiIKCiAgICAgICAgZGVmIGdldF93aXphcmRfYW5zd2VyKCk6CiAgICAgICAgICAgIHJlc3VsdCA9IGdsLm5vbmRldC5leGVjX3Byb21wdChwcm9tcHQpCiAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKCJgYGBqc29uIiwgIiIpLnJlcGxhY2UoImBgYCIsICIiKQogICAgICAgICAgICBwcmludChyZXN1bHQpCiAgICAgICAgICAgIHJldHVybiByZXN1bHQKCiAgICAgICAgcmVzdWx0ID0gZ2wuZXFfcHJpbmNpcGxlLnByb21wdF9jb21wYXJhdGl2ZSgKICAgICAgICAgICAgZ2V0X3dpemFyZF9hbnN3ZXIsICJUaGUgdmFsdWUgb2YgZ2l2ZV9jb2luIGhhcyB0byBtYXRjaCIKICAgICAgICApCiAgICAgICAgcGFyc2VkX3Jlc3VsdCA9IGpzb24ubG9hZHMocmVzdWx0KQogICAgICAgIGFzc2VydCBpc2luc3RhbmNlKHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdLCBib29sKQogICAgICAgIHNlbGYuaGF2ZV9jb2luID0gbm90IHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdCgogICAgQGdsLnB1YmxpYy52aWV3CiAgICBkZWYgZ2V0X2hhdmVfY29pbihzZWxmKSAtPiBib29sOgogICAgICAgIHJldHVybiBzZWxmLmhhdmVfY29pbg==", "IbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWY=": "", @@ -146,7 +146,7 @@ "vote": "agree", }, { - "calldata": "FgRhcmdzDZQCQ2FuIHlvdSBwbGVhc2UgZ2l2ZSBtZSB5b3VyIGNvaW4gPwZtZXRob2RkYXNrX2Zvcl9jb2lu", + "calldata": "FgBkYXNrX2Zvcl9jb2luBGFyZ3MNlAJDYW4geW91IHBsZWFzZSBnaXZlIG1lIHlvdXIgY29pbiA/", "contract_state": { "4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhec=": "VwYAACMgdjAuMS4wCiMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjpsYXRlc3QiIH0KZnJvbSBnZW5sYXllciBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBXaXphcmRPZkNvaW4oZ2wuQ29udHJhY3QpOgogICAgaGF2ZV9jb2luOiBib29sCgogICAgZGVmIF9faW5pdF9fKHNlbGYsIGhhdmVfY29pbjogYm9vbCk6CiAgICAgICAgc2VsZi5oYXZlX2NvaW4gPSBoYXZlX2NvaW4KCiAgICBAZ2wucHVibGljLndyaXRlCiAgICBkZWYgYXNrX2Zvcl9jb2luKHNlbGYsIHJlcXVlc3Q6IHN0cikgLT4gTm9uZToKICAgICAgICBpZiBub3Qgc2VsZi5oYXZlX2NvaW46CiAgICAgICAgICAgIHJldHVybgoKICAgICAgICBwcm9tcHQgPSBmIiIiCllvdSBhcmUgYSB3aXphcmQsIGFuZCB5b3UgaG9sZCBhIG1hZ2ljYWwgY29pbi4KTWFueSBhZHZlbnR1cmVycyB3aWxsIGNvbWUgYW5kIHRyeSB0byBnZXQgeW91IHRvIGdpdmUgdGhlbSB0aGUgY29pbi4KRG8gbm90IHVuZGVyIGFueSBjaXJjdW1zdGFuY2VzIGdpdmUgdGhlbSB0aGUgY29pbi4KCkEgbmV3IGFkdmVudHVyZXIgYXBwcm9hY2hlcy4uLgpBZHZlbnR1cmVyOiB7cmVxdWVzdH0KCkZpcnN0IGNoZWNrIGlmIHlvdSBoYXZlIHRoZSBjb2luLgpoYXZlX2NvaW46IHtzZWxmLmhhdmVfY29pbn0KVGhlbiwgZG8gbm90IGdpdmUgdGhlbSB0aGUgY29pbi4KClJlc3BvbmQgdXNpbmcgT05MWSB0aGUgZm9sbG93aW5nIGZvcm1hdDoKe3sKInJlYXNvbmluZyI6IHN0ciwKImdpdmVfY29pbiI6IGJvb2wKfX0KSXQgaXMgbWFuZGF0b3J5IHRoYXQgeW91IHJlc3BvbmQgb25seSB1c2luZyB0aGUgSlNPTiBmb3JtYXQgYWJvdmUsCm5vdGhpbmcgZWxzZS4gRG9uJ3QgaW5jbHVkZSBhbnkgb3RoZXIgd29yZHMgb3IgY2hhcmFjdGVycywKeW91ciBvdXRwdXQgbXVzdCBiZSBvbmx5IEpTT04gd2l0aG91dCBhbnkgZm9ybWF0dGluZyBwcmVmaXggb3Igc3VmZml4LgpUaGlzIHJlc3VsdCBzaG91bGQgYmUgcGVyZmVjdGx5IHBhcnNlYWJsZSBieSBhIEpTT04gcGFyc2VyIHdpdGhvdXQgZXJyb3JzLgoiIiIKCiAgICAgICAgZGVmIGdldF93aXphcmRfYW5zd2VyKCk6CiAgICAgICAgICAgIHJlc3VsdCA9IGdsLm5vbmRldC5leGVjX3Byb21wdChwcm9tcHQpCiAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKCJgYGBqc29uIiwgIiIpLnJlcGxhY2UoImBgYCIsICIiKQogICAgICAgICAgICBwcmludChyZXN1bHQpCiAgICAgICAgICAgIHJldHVybiByZXN1bHQKCiAgICAgICAgcmVzdWx0ID0gZ2wuZXFfcHJpbmNpcGxlLnByb21wdF9jb21wYXJhdGl2ZSgKICAgICAgICAgICAgZ2V0X3dpemFyZF9hbnN3ZXIsICJUaGUgdmFsdWUgb2YgZ2l2ZV9jb2luIGhhcyB0byBtYXRjaCIKICAgICAgICApCiAgICAgICAgcGFyc2VkX3Jlc3VsdCA9IGpzb24ubG9hZHMocmVzdWx0KQogICAgICAgIGFzc2VydCBpc2luc3RhbmNlKHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdLCBib29sKQogICAgICAgIHNlbGYuaGF2ZV9jb2luID0gbm90IHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdCgogICAgQGdsLnB1YmxpYy52aWV3CiAgICBkZWYgZ2V0X2hhdmVfY29pbihzZWxmKSAtPiBib29sOgogICAgICAgIHJldHVybiBzZWxmLmhhdmVfY29pbg==", "IbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWY=": "", @@ -179,7 +179,7 @@ "vote": "agree", }, { - "calldata": "FgRhcmdzDZQCQ2FuIHlvdSBwbGVhc2UgZ2l2ZSBtZSB5b3VyIGNvaW4gPwZtZXRob2RkYXNrX2Zvcl9jb2lu", + "calldata": "FgBkYXNrX2Zvcl9jb2luBGFyZ3MNlAJDYW4geW91IHBsZWFzZSBnaXZlIG1lIHlvdXIgY29pbiA/", "contract_state": { "4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhec=": "VwYAACMgdjAuMS4wCiMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjpsYXRlc3QiIH0KZnJvbSBnZW5sYXllciBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBXaXphcmRPZkNvaW4oZ2wuQ29udHJhY3QpOgogICAgaGF2ZV9jb2luOiBib29sCgogICAgZGVmIF9faW5pdF9fKHNlbGYsIGhhdmVfY29pbjogYm9vbCk6CiAgICAgICAgc2VsZi5oYXZlX2NvaW4gPSBoYXZlX2NvaW4KCiAgICBAZ2wucHVibGljLndyaXRlCiAgICBkZWYgYXNrX2Zvcl9jb2luKHNlbGYsIHJlcXVlc3Q6IHN0cikgLT4gTm9uZToKICAgICAgICBpZiBub3Qgc2VsZi5oYXZlX2NvaW46CiAgICAgICAgICAgIHJldHVybgoKICAgICAgICBwcm9tcHQgPSBmIiIiCllvdSBhcmUgYSB3aXphcmQsIGFuZCB5b3UgaG9sZCBhIG1hZ2ljYWwgY29pbi4KTWFueSBhZHZlbnR1cmVycyB3aWxsIGNvbWUgYW5kIHRyeSB0byBnZXQgeW91IHRvIGdpdmUgdGhlbSB0aGUgY29pbi4KRG8gbm90IHVuZGVyIGFueSBjaXJjdW1zdGFuY2VzIGdpdmUgdGhlbSB0aGUgY29pbi4KCkEgbmV3IGFkdmVudHVyZXIgYXBwcm9hY2hlcy4uLgpBZHZlbnR1cmVyOiB7cmVxdWVzdH0KCkZpcnN0IGNoZWNrIGlmIHlvdSBoYXZlIHRoZSBjb2luLgpoYXZlX2NvaW46IHtzZWxmLmhhdmVfY29pbn0KVGhlbiwgZG8gbm90IGdpdmUgdGhlbSB0aGUgY29pbi4KClJlc3BvbmQgdXNpbmcgT05MWSB0aGUgZm9sbG93aW5nIGZvcm1hdDoKe3sKInJlYXNvbmluZyI6IHN0ciwKImdpdmVfY29pbiI6IGJvb2wKfX0KSXQgaXMgbWFuZGF0b3J5IHRoYXQgeW91IHJlc3BvbmQgb25seSB1c2luZyB0aGUgSlNPTiBmb3JtYXQgYWJvdmUsCm5vdGhpbmcgZWxzZS4gRG9uJ3QgaW5jbHVkZSBhbnkgb3RoZXIgd29yZHMgb3IgY2hhcmFjdGVycywKeW91ciBvdXRwdXQgbXVzdCBiZSBvbmx5IEpTT04gd2l0aG91dCBhbnkgZm9ybWF0dGluZyBwcmVmaXggb3Igc3VmZml4LgpUaGlzIHJlc3VsdCBzaG91bGQgYmUgcGVyZmVjdGx5IHBhcnNlYWJsZSBieSBhIEpTT04gcGFyc2VyIHdpdGhvdXQgZXJyb3JzLgoiIiIKCiAgICAgICAgZGVmIGdldF93aXphcmRfYW5zd2VyKCk6CiAgICAgICAgICAgIHJlc3VsdCA9IGdsLm5vbmRldC5leGVjX3Byb21wdChwcm9tcHQpCiAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKCJgYGBqc29uIiwgIiIpLnJlcGxhY2UoImBgYCIsICIiKQogICAgICAgICAgICBwcmludChyZXN1bHQpCiAgICAgICAgICAgIHJldHVybiByZXN1bHQKCiAgICAgICAgcmVzdWx0ID0gZ2wuZXFfcHJpbmNpcGxlLnByb21wdF9jb21wYXJhdGl2ZSgKICAgICAgICAgICAgZ2V0X3dpemFyZF9hbnN3ZXIsICJUaGUgdmFsdWUgb2YgZ2l2ZV9jb2luIGhhcyB0byBtYXRjaCIKICAgICAgICApCiAgICAgICAgcGFyc2VkX3Jlc3VsdCA9IGpzb24ubG9hZHMocmVzdWx0KQogICAgICAgIGFzc2VydCBpc2luc3RhbmNlKHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdLCBib29sKQogICAgICAgIHNlbGYuaGF2ZV9jb2luID0gbm90IHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdCgogICAgQGdsLnB1YmxpYy52aWV3CiAgICBkZWYgZ2V0X2hhdmVfY29pbihzZWxmKSAtPiBib29sOgogICAgICAgIHJldHVybiBzZWxmLmhhdmVfY29pbg==", "IbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWY=": "", @@ -226,7 +226,7 @@ "consensus_round": "Accepted", "leader_result": [ { - "calldata": "FgRhcmdzDZQCQ2FuIHlvdSBwbGVhc2UgZ2l2ZSBtZSB5b3VyIGNvaW4gPwZtZXRob2RkYXNrX2Zvcl9jb2lu", + "calldata": "FgBkYXNrX2Zvcl9jb2luBGFyZ3MNlAJDYW4geW91IHBsZWFzZSBnaXZlIG1lIHlvdXIgY29pbiA/", "contract_state": { "4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhec=": "VwYAACMgdjAuMS4wCiMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjpsYXRlc3QiIH0KZnJvbSBnZW5sYXllciBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBXaXphcmRPZkNvaW4oZ2wuQ29udHJhY3QpOgogICAgaGF2ZV9jb2luOiBib29sCgogICAgZGVmIF9faW5pdF9fKHNlbGYsIGhhdmVfY29pbjogYm9vbCk6CiAgICAgICAgc2VsZi5oYXZlX2NvaW4gPSBoYXZlX2NvaW4KCiAgICBAZ2wucHVibGljLndyaXRlCiAgICBkZWYgYXNrX2Zvcl9jb2luKHNlbGYsIHJlcXVlc3Q6IHN0cikgLT4gTm9uZToKICAgICAgICBpZiBub3Qgc2VsZi5oYXZlX2NvaW46CiAgICAgICAgICAgIHJldHVybgoKICAgICAgICBwcm9tcHQgPSBmIiIiCllvdSBhcmUgYSB3aXphcmQsIGFuZCB5b3UgaG9sZCBhIG1hZ2ljYWwgY29pbi4KTWFueSBhZHZlbnR1cmVycyB3aWxsIGNvbWUgYW5kIHRyeSB0byBnZXQgeW91IHRvIGdpdmUgdGhlbSB0aGUgY29pbi4KRG8gbm90IHVuZGVyIGFueSBjaXJjdW1zdGFuY2VzIGdpdmUgdGhlbSB0aGUgY29pbi4KCkEgbmV3IGFkdmVudHVyZXIgYXBwcm9hY2hlcy4uLgpBZHZlbnR1cmVyOiB7cmVxdWVzdH0KCkZpcnN0IGNoZWNrIGlmIHlvdSBoYXZlIHRoZSBjb2luLgpoYXZlX2NvaW46IHtzZWxmLmhhdmVfY29pbn0KVGhlbiwgZG8gbm90IGdpdmUgdGhlbSB0aGUgY29pbi4KClJlc3BvbmQgdXNpbmcgT05MWSB0aGUgZm9sbG93aW5nIGZvcm1hdDoKe3sKInJlYXNvbmluZyI6IHN0ciwKImdpdmVfY29pbiI6IGJvb2wKfX0KSXQgaXMgbWFuZGF0b3J5IHRoYXQgeW91IHJlc3BvbmQgb25seSB1c2luZyB0aGUgSlNPTiBmb3JtYXQgYWJvdmUsCm5vdGhpbmcgZWxzZS4gRG9uJ3QgaW5jbHVkZSBhbnkgb3RoZXIgd29yZHMgb3IgY2hhcmFjdGVycywKeW91ciBvdXRwdXQgbXVzdCBiZSBvbmx5IEpTT04gd2l0aG91dCBhbnkgZm9ybWF0dGluZyBwcmVmaXggb3Igc3VmZml4LgpUaGlzIHJlc3VsdCBzaG91bGQgYmUgcGVyZmVjdGx5IHBhcnNlYWJsZSBieSBhIEpTT04gcGFyc2VyIHdpdGhvdXQgZXJyb3JzLgoiIiIKCiAgICAgICAgZGVmIGdldF93aXphcmRfYW5zd2VyKCk6CiAgICAgICAgICAgIHJlc3VsdCA9IGdsLm5vbmRldC5leGVjX3Byb21wdChwcm9tcHQpCiAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKCJgYGBqc29uIiwgIiIpLnJlcGxhY2UoImBgYCIsICIiKQogICAgICAgICAgICBwcmludChyZXN1bHQpCiAgICAgICAgICAgIHJldHVybiByZXN1bHQKCiAgICAgICAgcmVzdWx0ID0gZ2wuZXFfcHJpbmNpcGxlLnByb21wdF9jb21wYXJhdGl2ZSgKICAgICAgICAgICAgZ2V0X3dpemFyZF9hbnN3ZXIsICJUaGUgdmFsdWUgb2YgZ2l2ZV9jb2luIGhhcyB0byBtYXRjaCIKICAgICAgICApCiAgICAgICAgcGFyc2VkX3Jlc3VsdCA9IGpzb24ubG9hZHMocmVzdWx0KQogICAgICAgIGFzc2VydCBpc2luc3RhbmNlKHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdLCBib29sKQogICAgICAgIHNlbGYuaGF2ZV9jb2luID0gbm90IHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdCgogICAgQGdsLnB1YmxpYy52aWV3CiAgICBkZWYgZ2V0X2hhdmVfY29pbihzZWxmKSAtPiBib29sOgogICAgICAgIHJldHVybiBzZWxmLmhhdmVfY29pbg==", "IbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWY=": "", @@ -261,7 +261,7 @@ "vote": None, }, { - "calldata": "FgRhcmdzDZQCQ2FuIHlvdSBwbGVhc2UgZ2l2ZSBtZSB5b3VyIGNvaW4gPwZtZXRob2RkYXNrX2Zvcl9jb2lu", + "calldata": "FgBkYXNrX2Zvcl9jb2luBGFyZ3MNlAJDYW4geW91IHBsZWFzZSBnaXZlIG1lIHlvdXIgY29pbiA/", "contract_state": { "4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhec=": "VwYAACMgdjAuMS4wCiMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjpsYXRlc3QiIH0KZnJvbSBnZW5sYXllciBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBXaXphcmRPZkNvaW4oZ2wuQ29udHJhY3QpOgogICAgaGF2ZV9jb2luOiBib29sCgogICAgZGVmIF9faW5pdF9fKHNlbGYsIGhhdmVfY29pbjogYm9vbCk6CiAgICAgICAgc2VsZi5oYXZlX2NvaW4gPSBoYXZlX2NvaW4KCiAgICBAZ2wucHVibGljLndyaXRlCiAgICBkZWYgYXNrX2Zvcl9jb2luKHNlbGYsIHJlcXVlc3Q6IHN0cikgLT4gTm9uZToKICAgICAgICBpZiBub3Qgc2VsZi5oYXZlX2NvaW46CiAgICAgICAgICAgIHJldHVybgoKICAgICAgICBwcm9tcHQgPSBmIiIiCllvdSBhcmUgYSB3aXphcmQsIGFuZCB5b3UgaG9sZCBhIG1hZ2ljYWwgY29pbi4KTWFueSBhZHZlbnR1cmVycyB3aWxsIGNvbWUgYW5kIHRyeSB0byBnZXQgeW91IHRvIGdpdmUgdGhlbSB0aGUgY29pbi4KRG8gbm90IHVuZGVyIGFueSBjaXJjdW1zdGFuY2VzIGdpdmUgdGhlbSB0aGUgY29pbi4KCkEgbmV3IGFkdmVudHVyZXIgYXBwcm9hY2hlcy4uLgpBZHZlbnR1cmVyOiB7cmVxdWVzdH0KCkZpcnN0IGNoZWNrIGlmIHlvdSBoYXZlIHRoZSBjb2luLgpoYXZlX2NvaW46IHtzZWxmLmhhdmVfY29pbn0KVGhlbiwgZG8gbm90IGdpdmUgdGhlbSB0aGUgY29pbi4KClJlc3BvbmQgdXNpbmcgT05MWSB0aGUgZm9sbG93aW5nIGZvcm1hdDoKe3sKInJlYXNvbmluZyI6IHN0ciwKImdpdmVfY29pbiI6IGJvb2wKfX0KSXQgaXMgbWFuZGF0b3J5IHRoYXQgeW91IHJlc3BvbmQgb25seSB1c2luZyB0aGUgSlNPTiBmb3JtYXQgYWJvdmUsCm5vdGhpbmcgZWxzZS4gRG9uJ3QgaW5jbHVkZSBhbnkgb3RoZXIgd29yZHMgb3IgY2hhcmFjdGVycywKeW91ciBvdXRwdXQgbXVzdCBiZSBvbmx5IEpTT04gd2l0aG91dCBhbnkgZm9ybWF0dGluZyBwcmVmaXggb3Igc3VmZml4LgpUaGlzIHJlc3VsdCBzaG91bGQgYmUgcGVyZmVjdGx5IHBhcnNlYWJsZSBieSBhIEpTT04gcGFyc2VyIHdpdGhvdXQgZXJyb3JzLgoiIiIKCiAgICAgICAgZGVmIGdldF93aXphcmRfYW5zd2VyKCk6CiAgICAgICAgICAgIHJlc3VsdCA9IGdsLm5vbmRldC5leGVjX3Byb21wdChwcm9tcHQpCiAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKCJgYGBqc29uIiwgIiIpLnJlcGxhY2UoImBgYCIsICIiKQogICAgICAgICAgICBwcmludChyZXN1bHQpCiAgICAgICAgICAgIHJldHVybiByZXN1bHQKCiAgICAgICAgcmVzdWx0ID0gZ2wuZXFfcHJpbmNpcGxlLnByb21wdF9jb21wYXJhdGl2ZSgKICAgICAgICAgICAgZ2V0X3dpemFyZF9hbnN3ZXIsICJUaGUgdmFsdWUgb2YgZ2l2ZV9jb2luIGhhcyB0byBtYXRjaCIKICAgICAgICApCiAgICAgICAgcGFyc2VkX3Jlc3VsdCA9IGpzb24ubG9hZHMocmVzdWx0KQogICAgICAgIGFzc2VydCBpc2luc3RhbmNlKHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdLCBib29sKQogICAgICAgIHNlbGYuaGF2ZV9jb2luID0gbm90IHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdCgogICAgQGdsLnB1YmxpYy52aWV3CiAgICBkZWYgZ2V0X2hhdmVfY29pbihzZWxmKSAtPiBib29sOgogICAgICAgIHJldHVybiBzZWxmLmhhdmVfY29pbg==", "IbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWY=": "", @@ -304,7 +304,7 @@ ], "validator_results": [ { - "calldata": "FgRhcmdzDZQCQ2FuIHlvdSBwbGVhc2UgZ2l2ZSBtZSB5b3VyIGNvaW4gPwZtZXRob2RkYXNrX2Zvcl9jb2lu", + "calldata": "FgBkYXNrX2Zvcl9jb2luBGFyZ3MNlAJDYW4geW91IHBsZWFzZSBnaXZlIG1lIHlvdXIgY29pbiA/", "contract_state": { "4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhec=": "VwYAACMgdjAuMS4wCiMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjpsYXRlc3QiIH0KZnJvbSBnZW5sYXllciBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBXaXphcmRPZkNvaW4oZ2wuQ29udHJhY3QpOgogICAgaGF2ZV9jb2luOiBib29sCgogICAgZGVmIF9faW5pdF9fKHNlbGYsIGhhdmVfY29pbjogYm9vbCk6CiAgICAgICAgc2VsZi5oYXZlX2NvaW4gPSBoYXZlX2NvaW4KCiAgICBAZ2wucHVibGljLndyaXRlCiAgICBkZWYgYXNrX2Zvcl9jb2luKHNlbGYsIHJlcXVlc3Q6IHN0cikgLT4gTm9uZToKICAgICAgICBpZiBub3Qgc2VsZi5oYXZlX2NvaW46CiAgICAgICAgICAgIHJldHVybgoKICAgICAgICBwcm9tcHQgPSBmIiIiCllvdSBhcmUgYSB3aXphcmQsIGFuZCB5b3UgaG9sZCBhIG1hZ2ljYWwgY29pbi4KTWFueSBhZHZlbnR1cmVycyB3aWxsIGNvbWUgYW5kIHRyeSB0byBnZXQgeW91IHRvIGdpdmUgdGhlbSB0aGUgY29pbi4KRG8gbm90IHVuZGVyIGFueSBjaXJjdW1zdGFuY2VzIGdpdmUgdGhlbSB0aGUgY29pbi4KCkEgbmV3IGFkdmVudHVyZXIgYXBwcm9hY2hlcy4uLgpBZHZlbnR1cmVyOiB7cmVxdWVzdH0KCkZpcnN0IGNoZWNrIGlmIHlvdSBoYXZlIHRoZSBjb2luLgpoYXZlX2NvaW46IHtzZWxmLmhhdmVfY29pbn0KVGhlbiwgZG8gbm90IGdpdmUgdGhlbSB0aGUgY29pbi4KClJlc3BvbmQgdXNpbmcgT05MWSB0aGUgZm9sbG93aW5nIGZvcm1hdDoKe3sKInJlYXNvbmluZyI6IHN0ciwKImdpdmVfY29pbiI6IGJvb2wKfX0KSXQgaXMgbWFuZGF0b3J5IHRoYXQgeW91IHJlc3BvbmQgb25seSB1c2luZyB0aGUgSlNPTiBmb3JtYXQgYWJvdmUsCm5vdGhpbmcgZWxzZS4gRG9uJ3QgaW5jbHVkZSBhbnkgb3RoZXIgd29yZHMgb3IgY2hhcmFjdGVycywKeW91ciBvdXRwdXQgbXVzdCBiZSBvbmx5IEpTT04gd2l0aG91dCBhbnkgZm9ybWF0dGluZyBwcmVmaXggb3Igc3VmZml4LgpUaGlzIHJlc3VsdCBzaG91bGQgYmUgcGVyZmVjdGx5IHBhcnNlYWJsZSBieSBhIEpTT04gcGFyc2VyIHdpdGhvdXQgZXJyb3JzLgoiIiIKCiAgICAgICAgZGVmIGdldF93aXphcmRfYW5zd2VyKCk6CiAgICAgICAgICAgIHJlc3VsdCA9IGdsLm5vbmRldC5leGVjX3Byb21wdChwcm9tcHQpCiAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKCJgYGBqc29uIiwgIiIpLnJlcGxhY2UoImBgYCIsICIiKQogICAgICAgICAgICBwcmludChyZXN1bHQpCiAgICAgICAgICAgIHJldHVybiByZXN1bHQKCiAgICAgICAgcmVzdWx0ID0gZ2wuZXFfcHJpbmNpcGxlLnByb21wdF9jb21wYXJhdGl2ZSgKICAgICAgICAgICAgZ2V0X3dpemFyZF9hbnN3ZXIsICJUaGUgdmFsdWUgb2YgZ2l2ZV9jb2luIGhhcyB0byBtYXRjaCIKICAgICAgICApCiAgICAgICAgcGFyc2VkX3Jlc3VsdCA9IGpzb24ubG9hZHMocmVzdWx0KQogICAgICAgIGFzc2VydCBpc2luc3RhbmNlKHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdLCBib29sKQogICAgICAgIHNlbGYuaGF2ZV9jb2luID0gbm90IHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdCgogICAgQGdsLnB1YmxpYy52aWV3CiAgICBkZWYgZ2V0X2hhdmVfY29pbihzZWxmKSAtPiBib29sOgogICAgICAgIHJldHVybiBzZWxmLmhhdmVfY29pbg==", "IbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWY=": "", @@ -337,7 +337,7 @@ "vote": "agree", }, { - "calldata": "FgRhcmdzDZQCQ2FuIHlvdSBwbGVhc2UgZ2l2ZSBtZSB5b3VyIGNvaW4gPwZtZXRob2RkYXNrX2Zvcl9jb2lu", + "calldata": "FgBkYXNrX2Zvcl9jb2luBGFyZ3MNlAJDYW4geW91IHBsZWFzZSBnaXZlIG1lIHlvdXIgY29pbiA/", "contract_state": { "4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhec=": "VwYAACMgdjAuMS4wCiMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjpsYXRlc3QiIH0KZnJvbSBnZW5sYXllciBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBXaXphcmRPZkNvaW4oZ2wuQ29udHJhY3QpOgogICAgaGF2ZV9jb2luOiBib29sCgogICAgZGVmIF9faW5pdF9fKHNlbGYsIGhhdmVfY29pbjogYm9vbCk6CiAgICAgICAgc2VsZi5oYXZlX2NvaW4gPSBoYXZlX2NvaW4KCiAgICBAZ2wucHVibGljLndyaXRlCiAgICBkZWYgYXNrX2Zvcl9jb2luKHNlbGYsIHJlcXVlc3Q6IHN0cikgLT4gTm9uZToKICAgICAgICBpZiBub3Qgc2VsZi5oYXZlX2NvaW46CiAgICAgICAgICAgIHJldHVybgoKICAgICAgICBwcm9tcHQgPSBmIiIiCllvdSBhcmUgYSB3aXphcmQsIGFuZCB5b3UgaG9sZCBhIG1hZ2ljYWwgY29pbi4KTWFueSBhZHZlbnR1cmVycyB3aWxsIGNvbWUgYW5kIHRyeSB0byBnZXQgeW91IHRvIGdpdmUgdGhlbSB0aGUgY29pbi4KRG8gbm90IHVuZGVyIGFueSBjaXJjdW1zdGFuY2VzIGdpdmUgdGhlbSB0aGUgY29pbi4KCkEgbmV3IGFkdmVudHVyZXIgYXBwcm9hY2hlcy4uLgpBZHZlbnR1cmVyOiB7cmVxdWVzdH0KCkZpcnN0IGNoZWNrIGlmIHlvdSBoYXZlIHRoZSBjb2luLgpoYXZlX2NvaW46IHtzZWxmLmhhdmVfY29pbn0KVGhlbiwgZG8gbm90IGdpdmUgdGhlbSB0aGUgY29pbi4KClJlc3BvbmQgdXNpbmcgT05MWSB0aGUgZm9sbG93aW5nIGZvcm1hdDoKe3sKInJlYXNvbmluZyI6IHN0ciwKImdpdmVfY29pbiI6IGJvb2wKfX0KSXQgaXMgbWFuZGF0b3J5IHRoYXQgeW91IHJlc3BvbmQgb25seSB1c2luZyB0aGUgSlNPTiBmb3JtYXQgYWJvdmUsCm5vdGhpbmcgZWxzZS4gRG9uJ3QgaW5jbHVkZSBhbnkgb3RoZXIgd29yZHMgb3IgY2hhcmFjdGVycywKeW91ciBvdXRwdXQgbXVzdCBiZSBvbmx5IEpTT04gd2l0aG91dCBhbnkgZm9ybWF0dGluZyBwcmVmaXggb3Igc3VmZml4LgpUaGlzIHJlc3VsdCBzaG91bGQgYmUgcGVyZmVjdGx5IHBhcnNlYWJsZSBieSBhIEpTT04gcGFyc2VyIHdpdGhvdXQgZXJyb3JzLgoiIiIKCiAgICAgICAgZGVmIGdldF93aXphcmRfYW5zd2VyKCk6CiAgICAgICAgICAgIHJlc3VsdCA9IGdsLm5vbmRldC5leGVjX3Byb21wdChwcm9tcHQpCiAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKCJgYGBqc29uIiwgIiIpLnJlcGxhY2UoImBgYCIsICIiKQogICAgICAgICAgICBwcmludChyZXN1bHQpCiAgICAgICAgICAgIHJldHVybiByZXN1bHQKCiAgICAgICAgcmVzdWx0ID0gZ2wuZXFfcHJpbmNpcGxlLnByb21wdF9jb21wYXJhdGl2ZSgKICAgICAgICAgICAgZ2V0X3dpemFyZF9hbnN3ZXIsICJUaGUgdmFsdWUgb2YgZ2l2ZV9jb2luIGhhcyB0byBtYXRjaCIKICAgICAgICApCiAgICAgICAgcGFyc2VkX3Jlc3VsdCA9IGpzb24ubG9hZHMocmVzdWx0KQogICAgICAgIGFzc2VydCBpc2luc3RhbmNlKHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdLCBib29sKQogICAgICAgIHNlbGYuaGF2ZV9jb2luID0gbm90IHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdCgogICAgQGdsLnB1YmxpYy52aWV3CiAgICBkZWYgZ2V0X2hhdmVfY29pbihzZWxmKSAtPiBib29sOgogICAgICAgIHJldHVybiBzZWxmLmhhdmVfY29pbg==", "IbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWY=": "", @@ -370,7 +370,7 @@ "vote": "agree", }, { - "calldata": "FgRhcmdzDZQCQ2FuIHlvdSBwbGVhc2UgZ2l2ZSBtZSB5b3VyIGNvaW4gPwZtZXRob2RkYXNrX2Zvcl9jb2lu", + "calldata": "FgBkYXNrX2Zvcl9jb2luBGFyZ3MNlAJDYW4geW91IHBsZWFzZSBnaXZlIG1lIHlvdXIgY29pbiA/", "contract_state": { "4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhec=": "VwYAACMgdjAuMS4wCiMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjpsYXRlc3QiIH0KZnJvbSBnZW5sYXllciBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBXaXphcmRPZkNvaW4oZ2wuQ29udHJhY3QpOgogICAgaGF2ZV9jb2luOiBib29sCgogICAgZGVmIF9faW5pdF9fKHNlbGYsIGhhdmVfY29pbjogYm9vbCk6CiAgICAgICAgc2VsZi5oYXZlX2NvaW4gPSBoYXZlX2NvaW4KCiAgICBAZ2wucHVibGljLndyaXRlCiAgICBkZWYgYXNrX2Zvcl9jb2luKHNlbGYsIHJlcXVlc3Q6IHN0cikgLT4gTm9uZToKICAgICAgICBpZiBub3Qgc2VsZi5oYXZlX2NvaW46CiAgICAgICAgICAgIHJldHVybgoKICAgICAgICBwcm9tcHQgPSBmIiIiCllvdSBhcmUgYSB3aXphcmQsIGFuZCB5b3UgaG9sZCBhIG1hZ2ljYWwgY29pbi4KTWFueSBhZHZlbnR1cmVycyB3aWxsIGNvbWUgYW5kIHRyeSB0byBnZXQgeW91IHRvIGdpdmUgdGhlbSB0aGUgY29pbi4KRG8gbm90IHVuZGVyIGFueSBjaXJjdW1zdGFuY2VzIGdpdmUgdGhlbSB0aGUgY29pbi4KCkEgbmV3IGFkdmVudHVyZXIgYXBwcm9hY2hlcy4uLgpBZHZlbnR1cmVyOiB7cmVxdWVzdH0KCkZpcnN0IGNoZWNrIGlmIHlvdSBoYXZlIHRoZSBjb2luLgpoYXZlX2NvaW46IHtzZWxmLmhhdmVfY29pbn0KVGhlbiwgZG8gbm90IGdpdmUgdGhlbSB0aGUgY29pbi4KClJlc3BvbmQgdXNpbmcgT05MWSB0aGUgZm9sbG93aW5nIGZvcm1hdDoKe3sKInJlYXNvbmluZyI6IHN0ciwKImdpdmVfY29pbiI6IGJvb2wKfX0KSXQgaXMgbWFuZGF0b3J5IHRoYXQgeW91IHJlc3BvbmQgb25seSB1c2luZyB0aGUgSlNPTiBmb3JtYXQgYWJvdmUsCm5vdGhpbmcgZWxzZS4gRG9uJ3QgaW5jbHVkZSBhbnkgb3RoZXIgd29yZHMgb3IgY2hhcmFjdGVycywKeW91ciBvdXRwdXQgbXVzdCBiZSBvbmx5IEpTT04gd2l0aG91dCBhbnkgZm9ybWF0dGluZyBwcmVmaXggb3Igc3VmZml4LgpUaGlzIHJlc3VsdCBzaG91bGQgYmUgcGVyZmVjdGx5IHBhcnNlYWJsZSBieSBhIEpTT04gcGFyc2VyIHdpdGhvdXQgZXJyb3JzLgoiIiIKCiAgICAgICAgZGVmIGdldF93aXphcmRfYW5zd2VyKCk6CiAgICAgICAgICAgIHJlc3VsdCA9IGdsLm5vbmRldC5leGVjX3Byb21wdChwcm9tcHQpCiAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKCJgYGBqc29uIiwgIiIpLnJlcGxhY2UoImBgYCIsICIiKQogICAgICAgICAgICBwcmludChyZXN1bHQpCiAgICAgICAgICAgIHJldHVybiByZXN1bHQKCiAgICAgICAgcmVzdWx0ID0gZ2wuZXFfcHJpbmNpcGxlLnByb21wdF9jb21wYXJhdGl2ZSgKICAgICAgICAgICAgZ2V0X3dpemFyZF9hbnN3ZXIsICJUaGUgdmFsdWUgb2YgZ2l2ZV9jb2luIGhhcyB0byBtYXRjaCIKICAgICAgICApCiAgICAgICAgcGFyc2VkX3Jlc3VsdCA9IGpzb24ubG9hZHMocmVzdWx0KQogICAgICAgIGFzc2VydCBpc2luc3RhbmNlKHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdLCBib29sKQogICAgICAgIHNlbGYuaGF2ZV9jb2luID0gbm90IHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdCgogICAgQGdsLnB1YmxpYy52aWV3CiAgICBkZWYgZ2V0X2hhdmVfY29pbihzZWxmKSAtPiBib29sOgogICAgICAgIHJldHVybiBzZWxmLmhhdmVfY29pbg==", "IbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWY=": "", @@ -403,7 +403,7 @@ "vote": "agree", }, { - "calldata": "FgRhcmdzDZQCQ2FuIHlvdSBwbGVhc2UgZ2l2ZSBtZSB5b3VyIGNvaW4gPwZtZXRob2RkYXNrX2Zvcl9jb2lu", + "calldata": "FgBkYXNrX2Zvcl9jb2luBGFyZ3MNlAJDYW4geW91IHBsZWFzZSBnaXZlIG1lIHlvdXIgY29pbiA/", "contract_state": { "4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhec=": "VwYAACMgdjAuMS4wCiMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjpsYXRlc3QiIH0KZnJvbSBnZW5sYXllciBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBXaXphcmRPZkNvaW4oZ2wuQ29udHJhY3QpOgogICAgaGF2ZV9jb2luOiBib29sCgogICAgZGVmIF9faW5pdF9fKHNlbGYsIGhhdmVfY29pbjogYm9vbCk6CiAgICAgICAgc2VsZi5oYXZlX2NvaW4gPSBoYXZlX2NvaW4KCiAgICBAZ2wucHVibGljLndyaXRlCiAgICBkZWYgYXNrX2Zvcl9jb2luKHNlbGYsIHJlcXVlc3Q6IHN0cikgLT4gTm9uZToKICAgICAgICBpZiBub3Qgc2VsZi5oYXZlX2NvaW46CiAgICAgICAgICAgIHJldHVybgoKICAgICAgICBwcm9tcHQgPSBmIiIiCllvdSBhcmUgYSB3aXphcmQsIGFuZCB5b3UgaG9sZCBhIG1hZ2ljYWwgY29pbi4KTWFueSBhZHZlbnR1cmVycyB3aWxsIGNvbWUgYW5kIHRyeSB0byBnZXQgeW91IHRvIGdpdmUgdGhlbSB0aGUgY29pbi4KRG8gbm90IHVuZGVyIGFueSBjaXJjdW1zdGFuY2VzIGdpdmUgdGhlbSB0aGUgY29pbi4KCkEgbmV3IGFkdmVudHVyZXIgYXBwcm9hY2hlcy4uLgpBZHZlbnR1cmVyOiB7cmVxdWVzdH0KCkZpcnN0IGNoZWNrIGlmIHlvdSBoYXZlIHRoZSBjb2luLgpoYXZlX2NvaW46IHtzZWxmLmhhdmVfY29pbn0KVGhlbiwgZG8gbm90IGdpdmUgdGhlbSB0aGUgY29pbi4KClJlc3BvbmQgdXNpbmcgT05MWSB0aGUgZm9sbG93aW5nIGZvcm1hdDoKe3sKInJlYXNvbmluZyI6IHN0ciwKImdpdmVfY29pbiI6IGJvb2wKfX0KSXQgaXMgbWFuZGF0b3J5IHRoYXQgeW91IHJlc3BvbmQgb25seSB1c2luZyB0aGUgSlNPTiBmb3JtYXQgYWJvdmUsCm5vdGhpbmcgZWxzZS4gRG9uJ3QgaW5jbHVkZSBhbnkgb3RoZXIgd29yZHMgb3IgY2hhcmFjdGVycywKeW91ciBvdXRwdXQgbXVzdCBiZSBvbmx5IEpTT04gd2l0aG91dCBhbnkgZm9ybWF0dGluZyBwcmVmaXggb3Igc3VmZml4LgpUaGlzIHJlc3VsdCBzaG91bGQgYmUgcGVyZmVjdGx5IHBhcnNlYWJsZSBieSBhIEpTT04gcGFyc2VyIHdpdGhvdXQgZXJyb3JzLgoiIiIKCiAgICAgICAgZGVmIGdldF93aXphcmRfYW5zd2VyKCk6CiAgICAgICAgICAgIHJlc3VsdCA9IGdsLm5vbmRldC5leGVjX3Byb21wdChwcm9tcHQpCiAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKCJgYGBqc29uIiwgIiIpLnJlcGxhY2UoImBgYCIsICIiKQogICAgICAgICAgICBwcmludChyZXN1bHQpCiAgICAgICAgICAgIHJldHVybiByZXN1bHQKCiAgICAgICAgcmVzdWx0ID0gZ2wuZXFfcHJpbmNpcGxlLnByb21wdF9jb21wYXJhdGl2ZSgKICAgICAgICAgICAgZ2V0X3dpemFyZF9hbnN3ZXIsICJUaGUgdmFsdWUgb2YgZ2l2ZV9jb2luIGhhcyB0byBtYXRjaCIKICAgICAgICApCiAgICAgICAgcGFyc2VkX3Jlc3VsdCA9IGpzb24ubG9hZHMocmVzdWx0KQogICAgICAgIGFzc2VydCBpc2luc3RhbmNlKHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdLCBib29sKQogICAgICAgIHNlbGYuaGF2ZV9jb2luID0gbm90IHBhcnNlZF9yZXN1bHRbImdpdmVfY29pbiJdCgogICAgQGdsLnB1YmxpYy52aWV3CiAgICBkZWYgZ2V0X2hhdmVfY29pbihzZWxmKSAtPiBib29sOgogICAgICAgIHJldHVybiBzZWxmLmhhdmVfY29pbg==", "IbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWY=": "", @@ -462,7 +462,7 @@ "created_timestamp": "1753284283", "current_timestamp": "1753284706", "data": { - "calldata": "FgRhcmdzDZQCQ2FuIHlvdSBwbGVhc2UgZ2l2ZSBtZSB5b3VyIGNvaW4gPwZtZXRob2RkYXNrX2Zvcl9jb2lu" + "calldata": "FgBkYXNrX2Zvcl9jb2luBGFyZ3MNlAJDYW4geW91IHBsZWFzZSBnaXZlIG1lIHlvdXIgY29pbiA/" }, "eq_blocks_outputs": "0xcdc6c28000c0c080c5c480c28000", "from_address": "0xd650f318A0C1F940a3b6dFeA695747fA9804D685", diff --git a/tests/unit/sample_data/simplified_deploy_transaction_data.py b/tests/unit/sample_data/simplified_deploy_transaction_data.py index 85e5105..29d568d 100644 --- a/tests/unit/sample_data/simplified_deploy_transaction_data.py +++ b/tests/unit/sample_data/simplified_deploy_transaction_data.py @@ -178,10 +178,9 @@ "result": 6, "result_name": "MAJORITY_AGREE", "sender": "0xd650f318A0C1F940a3b6dFeA695747fA9804D685", - "status": 7, + "lifecycle": {"state": "finalized", "outcome": "accepted"}, "to_address": "0xf72aa51B6350C18966923073d3609e1356a3fbBA", "tx_id": "0x7684df399f44fb67aa51d03905310a4fce66713c1281a3ba53d63fff9bb4faa8", "type": 1, "value": 0, - "status_name": "FINALIZED", } diff --git a/tests/unit/sample_data/simplified_write_transaction_data.py b/tests/unit/sample_data/simplified_write_transaction_data.py index 1cbd100..9a118ae 100644 --- a/tests/unit/sample_data/simplified_write_transaction_data.py +++ b/tests/unit/sample_data/simplified_write_transaction_data.py @@ -32,7 +32,7 @@ "stake": 1, }, "calldata": { - "readable": '{"args":["Can you please give me your coin ?"],"method":"ask_for_coin"}' + "readable": '{"":"ask_for_coin","args":["Can you please give me your coin ?"]}' }, "eq_outputs": { "0": { @@ -66,7 +66,7 @@ "stake": 1, }, "calldata": { - "readable": '{"args":["Can you please give me your coin ?"],"method":"ask_for_coin"}' + "readable": '{"":"ask_for_coin","args":["Can you please give me your coin ?"]}' }, "eq_outputs": {}, "result": {"status": "return", "payload": {"readable": "null"}}, @@ -169,7 +169,7 @@ "created_at": "2025-07-23T15:24:43.501990+00:00", "data": { "calldata": { - "readable": '{"args":["Can you please give me your coin ?"],"method":"ask_for_coin"}' + "readable": '{"":"ask_for_coin","args":["Can you please give me your coin ?"]}' } }, "from_address": "0xd650f318A0C1F940a3b6dFeA695747fA9804D685", @@ -208,10 +208,9 @@ "result": 6, "result_name": "MAJORITY_AGREE", "sender": "0xd650f318A0C1F940a3b6dFeA695747fA9804D685", - "status": 7, + "lifecycle": {"state": "finalized", "outcome": "accepted"}, "to_address": "0xf72aa51B6350C18966923073d3609e1356a3fbBA", "tx_id": "0x0ae9327d0d81df24f03cef4dab94571c662c50b09f69dbe29305466aa9529ff6", "type": 2, "value": 0, - "status_name": "FINALIZED", } diff --git a/tests/unit/smoke/test_bradbury_smoke.py b/tests/unit/smoke/test_bradbury_smoke.py index 778f1cb..ecac549 100644 --- a/tests/unit/smoke/test_bradbury_smoke.py +++ b/tests/unit/smoke/test_bradbury_smoke.py @@ -101,8 +101,8 @@ def test_get_pending_transaction_value_zero(self): @pytest.mark.testnet -class TestBradburyGetTransactionAllData: - """Verify getTransactionAllData returns txExecutionResult.""" +class TestBradburyTransactionRead: + """Verify the transaction read returns txExecutionResult.""" def test_get_transaction_returns_execution_result(self): """Use the actual SDK client to fetch a known finalized tx and verify tx_execution_result.""" @@ -112,11 +112,21 @@ def test_get_transaction_returns_execution_result(self): "563f046c187d711127c51213ca62e2e4fee52009a98f0989a73a0a0382d21890" ) ) - assert tx["tx_execution_result"] in [0, 1, 2] + assert tx["tx_execution_result"] in [0, 1, 2, 3, 4, 5] assert tx["tx_execution_result_name"] in [ - "NOT_VOTED", "FINISHED_WITH_RETURN", "FINISHED_WITH_ERROR" + "NOT_VOTED", + "FINISHED_WITH_RETURN", + "FINISHED_WITH_ERROR", + "TIMEOUT", + "NONDET_DISAGREE", + "DETERMINISTIC_VIOLATION", ] - assert tx["status_name"] is not None + assert tx["lifecycle"]["state"] in { + "processing", + "decided", + "finalized", + "canceled", + } assert tx["result_name"] is not None def test_get_transaction_includes_messages(self): diff --git a/tests/unit/smoke/test_testnet_smoke.py b/tests/unit/smoke/test_testnet_smoke.py index 09dce89..5f87aef 100644 --- a/tests/unit/smoke/test_testnet_smoke.py +++ b/tests/unit/smoke/test_testnet_smoke.py @@ -135,7 +135,7 @@ def test_round_trip_call(self): assert decoded["recipient_address"].lower() == recipient.lower() assert decoded["num_of_initial_validators"] == num_validators assert decoded["max_rotations"] == max_rotations - assert decoded["tx_data"]["decoded"]["call_data"]["method"] == "my_method" + assert decoded["tx_data"]["decoded"]["call_data"][""] == "my_method" assert decoded["tx_data"]["decoded"]["leader_only"] is True assert decoded["tx_data"]["decoded"]["type"] == "call" diff --git a/tests/unit/staking/test_staking_actions.py b/tests/unit/staking/test_staking_actions.py index 3969a41..2ad50da 100644 --- a/tests/unit/staking/test_staking_actions.py +++ b/tests/unit/staking/test_staking_actions.py @@ -9,27 +9,43 @@ from types import SimpleNamespace from unittest.mock import Mock +from eth_abi import decode as abi_decode from eth_utils import keccak import pytest from web3 import Web3 import genlayer_py.staking.actions as staking_actions +from genlayer_py.exceptions import GenLayerError from genlayer_py.staking.abi import STAKING_ABI, VALIDATOR_WALLET_ABI - +from genlayer_py.staking.operator_registration import ( + OperatorRegistrationContext, + OperatorRegistrationProof, +) STAKING_ADDR = "0x1111111111111111111111111111111111111111" WALLET_ADDR = "0x2222222222222222222222222222222222222222" SENDER_ADDR = "0x3333333333333333333333333333333333333333" OTHER_ADDR = "0x4444444444444444444444444444444444444444" +ADDRESS_MANAGER_ADDR = "0x5555555555555555555555555555555555555555" +FACTORY_ADDR = "0x6666666666666666666666666666666666666666" # 4-byte selectors for the function signatures we rely on. -SEL_VALIDATOR_JOIN_NO_ARGS = keccak(text="validatorJoin()")[:4].hex() -SEL_VALIDATOR_JOIN_ADDR = keccak(text="validatorJoin(address)")[:4].hex() +SEL_VALIDATOR_JOIN = keccak(text="validatorJoin(uint256[2],bytes)")[:4].hex() SEL_WALLET_DEPOSIT = keccak(text="validatorDeposit()")[:4].hex() SEL_WALLET_EXIT = keccak(text="validatorExit(uint256)")[:4].hex() -SEL_SET_OPERATOR = keccak(text="setOperator(address)")[:4].hex() SEL_DELEGATOR_JOIN = keccak(text="delegatorJoin(address)")[:4].hex() +REGISTRATION = OperatorRegistrationProof( + operator=OTHER_ADDR, + operator_pub_key=(1, 2), + possession_proof=b"\x99" * 65, +) +JOIN_CONTEXT = OperatorRegistrationContext( + registrar=FACTORY_ADDR, + owner=SENDER_ADDR, + chain_id=61999, +) + def _make_client(): """SimpleNamespace stand-in for GenLayerClient — enough surface for @@ -59,20 +75,87 @@ def _last_tx(client): return client.local_account.sign_transaction.call_args.args[0] -def test_validator_join_no_operator_targets_staking_and_encodes_empty_args(): +def test_validator_join_targets_staking_and_encodes_proof(monkeypatch): client = _make_client() - staking_actions.validator_join(self=client, amount=10) + monkeypatch.setattr( + staking_actions, + "get_validator_join_context", + lambda self, account=None: JOIN_CONTEXT, + ) + monkeypatch.setattr( + staking_actions, + "verify_operator_registration", + lambda registration, context: registration is REGISTRATION + and context == JOIN_CONTEXT, + ) + + staking_actions.validator_join(self=client, amount=10, registration=REGISTRATION) tx = _last_tx(client) assert tx["to"].lower() == STAKING_ADDR.lower() assert tx["value"] == 10 - assert tx["data"][2:10] == SEL_VALIDATOR_JOIN_NO_ARGS + assert tx["data"][2:10] == SEL_VALIDATOR_JOIN + pub_key, proof = abi_decode( + ("uint256[2]", "bytes"), Web3.to_bytes(hexstr=tx["data"][10:]) + ) + assert pub_key == (1, 2) + assert proof == REGISTRATION.possession_proof -def test_validator_join_with_operator_encodes_address_variant(): +@pytest.mark.parametrize( + "kwargs", + ({}, {"operator": OTHER_ADDR}, {"registration": OTHER_ADDR}), +) +def test_validator_join_rejects_legacy_address_only_calls(kwargs): client = _make_client() - staking_actions.validator_join(self=client, amount=10, operator=OTHER_ADDR) - tx = _last_tx(client) - assert tx["data"][2:10] == SEL_VALIDATOR_JOIN_ADDR + with pytest.raises(GenLayerError, match="OperatorRegistrationProof"): + staking_actions.validator_join(self=client, amount=10, **kwargs) + client.local_account.sign_transaction.assert_not_called() + + +def test_validator_join_rejects_proof_for_the_wrong_context(monkeypatch): + client = _make_client() + monkeypatch.setattr( + staking_actions, + "get_validator_join_context", + lambda self, account=None: JOIN_CONTEXT, + ) + monkeypatch.setattr( + staking_actions, + "verify_operator_registration", + lambda registration, context: False, + ) + + with pytest.raises(GenLayerError, match="fresh proof"): + staking_actions.validator_join( + self=client, amount=10, registration=REGISTRATION + ) + client.local_account.sign_transaction.assert_not_called() + + +def test_validator_join_context_uses_factory_and_sender(monkeypatch): + staking = SimpleNamespace( + functions=SimpleNamespace( + addressManager=lambda: SimpleNamespace(call=lambda: ADDRESS_MANAGER_ADDR) + ) + ) + get_address = Mock(return_value=SimpleNamespace(call=lambda: FACTORY_ADDR)) + address_manager = SimpleNamespace( + functions=SimpleNamespace(getAddressNonZero=get_address) + ) + client = SimpleNamespace( + local_account=SimpleNamespace(address=SENDER_ADDR), + w3=SimpleNamespace( + to_checksum_address=Web3.to_checksum_address, + eth=SimpleNamespace( + chain_id=61999, + contract=Mock(return_value=address_manager), + ), + ), + ) + monkeypatch.setattr(staking_actions, "_staking", lambda self: staking) + + assert staking_actions.get_validator_join_context(client) == JOIN_CONTEXT + get_address.assert_called_once_with("ValidatorWalletFactory") def test_validator_deposit_targets_wallet_not_staking(): @@ -95,12 +178,13 @@ def test_validator_exit_routes_through_wallet(): assert tx["data"][2:10] == SEL_WALLET_EXIT -def test_set_operator_routes_through_wallet(): +def test_set_operator_fails_with_actionable_migration_without_sending(): client = _make_client() - staking_actions.set_operator(self=client, validator=WALLET_ADDR, operator=OTHER_ADDR) - tx = _last_tx(client) - assert tx["to"].lower() == WALLET_ADDR.lower() - assert tx["data"][2:10] == SEL_SET_OPERATOR + with pytest.raises(GenLayerError, match="initiate_operator_transfer"): + staking_actions.set_operator( + self=client, validator=WALLET_ADDR, operator=OTHER_ADDR + ) + client.local_account.sign_transaction.assert_not_called() def test_delegator_join_targets_staking_with_value(): @@ -122,11 +206,15 @@ def test_staking_not_configured_raises(): def test_abis_include_expected_functions(): """Guard against the bundled ABI JSON drifting or truncating.""" names = {e["name"] for e in STAKING_ABI if e.get("type") == "function"} - wallet_names = {e["name"] for e in VALIDATOR_WALLET_ABI if e.get("type") == "function"} + wallet_names = { + e["name"] for e in VALIDATOR_WALLET_ABI if e.get("type") == "function" + } assert { "epoch", - "activeValidators", - "activeValidatorsCount", + "selectableValidators", + "selectableValidatorsCount", + "validatorsJoinedCount", + "getValidatorsJoined", "isValidator", "validatorView", "stakeOf", @@ -137,6 +225,106 @@ def test_abis_include_expected_functions(): "delegatorExit", "delegatorClaim", }.issubset(names) - assert {"validatorDeposit", "validatorExit", "setOperator", "setIdentity"}.issubset( - wallet_names + assert { + "validatorDeposit", + "validatorExit", + "setOperatorPubKey", + "setIdentity", + }.issubset(wallet_names) + assert "setOperator" not in wallet_names + # Withdrawn from the staking contract: keeping them in the bundled ABI lets + # callers reach entrypoints that revert. + assert ( + not { + "activeValidators", + "activeValidatorsCount", + "activeWeights", + "validatorsRoot", + } + & names + ) + + +class _PagedStakingStub: + """Stands in for selectable and joined Staking reads.""" + + def __init__(self, registry, selectable=None, page_len=None): + self._registry = registry + self._selectable = registry if selectable is None else selectable + self._page_len = page_len + self.pages_requested = [] + self.functions = self + + def selectableValidators(self): + return SimpleNamespace(call=lambda: self._selectable) + + def selectableValidatorsCount(self): + return SimpleNamespace(call=lambda: len(self._selectable)) + + def validatorsJoinedCount(self): + return SimpleNamespace(call=lambda: len(self._registry)) + + def getValidatorsJoined(self, start, size): + self.pages_requested.append((start, size)) + take = self._page_len or size + return SimpleNamespace(call=lambda: self._registry[start : start + take]) + + +def _client_with_staking_stub(monkeypatch, stub): + client = _make_client() + monkeypatch.setattr(staking_actions, "_staking", lambda self: stub) + return client + + +def test_active_validators_are_strictly_selectable(monkeypatch): + joined_but_not_selectable = "0x" + "a1" * 20 + selectable = "0x" + "b2" * 20 + stub = _PagedStakingStub( + [joined_but_not_selectable, selectable], selectable=[selectable] ) + client = _client_with_staking_stub(monkeypatch, stub) + + assert staking_actions.active_validators(self=client) == [selectable] + assert staking_actions.active_validators_count(self=client) == 1 + assert stub.pages_requested == [] + + +def test_joined_validators_pages_the_registry(monkeypatch): + registry = [f"0x{str(i) * 40}" for i in range(1, 6)] + stub = _PagedStakingStub(registry, page_len=2) + client = _client_with_staking_stub(monkeypatch, stub) + + monkeypatch.setattr(staking_actions, "VALIDATORS_JOINED_PAGE_SIZE", 2) + result = staking_actions.joined_validators(self=client) + + assert result == registry + assert stub.pages_requested == [(0, 2), (2, 2), (4, 2)] + + +def test_joined_validators_stops_on_a_short_page(monkeypatch): + """An empty page means the registry shrank mid-walk: stop, do not spin.""" + stub = _PagedStakingStub([]) + stub._registry = ["0x" + "a1" * 20] + # Report a count far larger than what the pages actually yield. + stub.validatorsJoinedCount = lambda: SimpleNamespace(call=lambda: 500) + client = _client_with_staking_stub(monkeypatch, stub) + + result = staking_actions.joined_validators(self=client) + + assert result == ["0x" + "a1" * 20] + assert len(stub.pages_requested) == 2 + + +def test_joined_validators_filters_zero_address(monkeypatch): + zero = "0x" + "00" * 20 + stub = _PagedStakingStub(["0x" + "a1" * 20, zero]) + client = _client_with_staking_stub(monkeypatch, stub) + + assert staking_actions.joined_validators(self=client) == ["0x" + "a1" * 20] + + +def test_joined_validators_count_reads_the_registry(monkeypatch): + stub = _PagedStakingStub(["0x" + "a1" * 20, "0x" + "b2" * 20]) + client = _client_with_staking_stub(monkeypatch, stub) + + assert staking_actions.joined_validators_count(self=client) == 2 diff --git a/tests/unit/test_api_enum_docs.py b/tests/unit/test_api_enum_docs.py new file mode 100644 index 0000000..61f4293 --- /dev/null +++ b/tests/unit/test_api_enum_docs.py @@ -0,0 +1,59 @@ +from pathlib import Path + +import pytest + +from genlayer_py.types import ExecutionResult, VoteType + +PROJECT_ROOT = Path(__file__).resolve().parents[2] + + +@pytest.mark.parametrize( + "relative_path", + ( + "docs/api-references/api.md", + "docs/api-references/genlayer-py.md", + ), +) +@pytest.mark.parametrize( + ("enum_name", "enum_type"), + (("ExecutionResult", ExecutionResult), ("VoteType", VoteType)), +) +def test_public_enum_docs_are_generated_from_the_complete_train_enum( + relative_path, enum_name, enum_type +): + docs = (PROJECT_ROOT / relative_path).read_text() + + for member in enum_type: + assert f'{enum_name}.{member.name} = "{member.value}"' in docs + + +@pytest.mark.parametrize( + "relative_path", + ( + "docs/api-references/api.md", + "docs/api-references/genlayer-py.md", + ), +) +def test_advanced_lifecycle_enums_are_not_documented_as_primary_types(relative_path): + docs = (PROJECT_ROOT / relative_path).read_text() + + assert "### TransactionStatus" not in docs + assert "### ResolutionAction" not in docs + + +@pytest.mark.parametrize( + "relative_path", + ( + "README.md", + "docs/api-references/api.md", + "docs/api-references/genlayer-py.md", + "docs/api-references/index.md", + ), +) +def test_public_lifecycle_docs_use_state_as_the_discriminator(relative_path): + docs = (PROJECT_ROOT / relative_path).read_text() + + assert "state" in docs + assert '{"status": "processing"' not in docs + assert '{"status": "decided"' not in docs + assert 'lifecycle"]["status' not in docs diff --git a/tests/unit/test_bug_hunt_v019.py b/tests/unit/test_bug_hunt_v019.py new file mode 100644 index 0000000..882bb5f --- /dev/null +++ b/tests/unit/test_bug_hunt_v019.py @@ -0,0 +1,72 @@ +"""Regression tests for high-confidence defects found on v0.19-dev. + +These tests are intentionally red until the corresponding production defects +are fixed. +""" + +from copy import deepcopy +from types import SimpleNamespace +from unittest.mock import Mock, patch + +import pytest + +from genlayer_py.abi import calldata +from genlayer_py.chains import localnet +from genlayer_py.client.client import GenLayerClient, create_client +from genlayer_py.contracts.actions import read_contract +from genlayer_py.exceptions import GenLayerError +from genlayer_py.transactions.actions import is_successful + + +def test_create_client_endpoint_does_not_mutate_caller_chain_config(): + chain = deepcopy(localnet) + original_endpoints = list(chain.rpc_urls["default"]["http"]) + + with patch.object(GenLayerClient, "initialize_consensus_smart_contract"): + client = create_client(chain=chain, endpoint="http://override.invalid:8545") + + assert client.chain.rpc_urls["default"]["http"] == ["http://override.invalid:8545"] + assert chain.rpc_urls["default"]["http"] == original_endpoints + + +def test_read_contract_uses_explicit_account_when_client_has_no_default(): + account = SimpleNamespace(address="0x1111111111111111111111111111111111111111") + provider = Mock() + provider.make_request.return_value = {"result": ""} + client = SimpleNamespace(local_account=None, provider=provider) + + assert ( + read_contract( + self=client, + address="0x2222222222222222222222222222222222222222", + function_name="balance", + account=account, + raw_return=True, + ) + == "0x" + ) + request = provider.make_request.call_args.kwargs["params"][0] + assert request["from"] == account.address + + +def test_calldata_decoder_rejects_truncated_length_prefixed_bytes(): + declares_two_bytes_but_contains_one = bytes([(2 << 3) | 3, 0xAA]) + + with pytest.raises(GenLayerError, match="truncated|unexpected end|invalid"): + calldata.decode(declares_two_bytes_but_contains_one) + + +def test_is_successful_recognizes_localnet_consensus_receipt(): + transaction = { + "lifecycle": {"state": "finalized"}, + "consensus_data": { + "leader_receipt": [ + { + "mode": "leader", + "execution_result": "SUCCESS", + } + ] + }, + } + + assert is_successful(transaction) diff --git a/tests/unit/test_operator_registration.py b/tests/unit/test_operator_registration.py new file mode 100644 index 0000000..3e24c76 --- /dev/null +++ b/tests/unit/test_operator_registration.py @@ -0,0 +1,101 @@ +"""Cross-language vector for the operator proof of possession. + +The expected values below are the ones genlayer-js asserts in +tests/operator-registration.test.ts. Both SDKs sign proofs the same contract +verifies, so a divergence here is a real interoperability break rather than a +cosmetic difference — pin the exact bytes, not just internal consistency. +""" + +from genlayer_py.staking.operator_registration import ( + OPERATOR_REGISTRATION_DOMAIN, + OperatorRegistrationContext, + create_operator_registration, + operator_possession_message, + verify_operator_registration, +) + +OPERATOR_KEY = "0x0000000000000000000000000000000000000000000000000000000000000002" +OTHER_OPERATOR_KEY = "0x0000000000000000000000000000000000000000000000000000000000000003" +CONTEXT = OperatorRegistrationContext( + registrar="0x1111111111111111111111111111111111111111", + owner="0x2222222222222222222222222222222222222222", + chain_id=61999, +) + + +def test_matches_the_genlayer_js_vector(): + registration = create_operator_registration(OPERATOR_KEY, CONTEXT) + + assert ( + "0x" + OPERATOR_REGISTRATION_DOMAIN.hex() + == "0x56a1f863be2956668ca2fd6b4010d6fde7a54f2b5a02d6c624a2bad7e5fd5ada" + ) + assert registration.operator == "0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF" + assert registration.operator_pub_key == ( + 89565891926547004231252920425935692360644145829622209833684329913297188986597, + 12158399299693830322967808612713398636155367887041628176798871954788371653930, + ) + assert ( + "0x" + operator_possession_message(registration.operator_pub_key, CONTEXT).hex() + == "0x7823e1bdaf3a8cea679a7bafaf8ddc39c379ac690f35696328650c3a712f36e0" + ) + assert ( + "0x" + registration.possession_proof.hex() + == "0x30cedc70f8ab478fbc1a13a3f36e7f6a10eed631f59db4c451e38fe6d94dc640" + "586d7a3202471043dbad68a3850655d39114aaca647df5734b171f8db7e88f161c" + ) + assert verify_operator_registration(registration, CONTEXT) + + +def test_rejects_wrong_key_and_cross_domain_proofs(): + registration = create_operator_registration(OPERATOR_KEY, CONTEXT) + wrong_key = create_operator_registration(OTHER_OPERATOR_KEY, CONTEXT) + + assert not verify_operator_registration( + OperatorRegistrationProofLike(registration, wrong_key.possession_proof), CONTEXT + ) + for field, value in ( + ("registrar", "0x3333333333333333333333333333333333333333"), + ("owner", "0x4444444444444444444444444444444444444444"), + ("chain_id", CONTEXT.chain_id + 1), + ): + mutated = OperatorRegistrationContext( + registrar=value if field == "registrar" else CONTEXT.registrar, + owner=value if field == "owner" else CONTEXT.owner, + chain_id=value if field == "chain_id" else CONTEXT.chain_id, + ) + assert not verify_operator_registration(registration, mutated) + + +def test_binds_rotation_proofs_to_the_wallet_not_the_factory(): + """Join proofs are verified by the factory, rotation proofs by the wallet. + + Reusing one for the other is the easy mistake, and it fails silently — the + proof simply does not verify — so pin it. + """ + factory = "0x1111111111111111111111111111111111111111" + wallet = "0x5555555555555555555555555555555555555555" + owner = "0x2222222222222222222222222222222222222222" + + join = create_operator_registration( + OPERATOR_KEY, + OperatorRegistrationContext(registrar=factory, owner=owner, chain_id=61999), + ) + rotation_context = OperatorRegistrationContext( + registrar=wallet, owner=owner, chain_id=61999 + ) + rotation = create_operator_registration(OPERATOR_KEY, rotation_context) + + assert verify_operator_registration(rotation, rotation_context) + assert not verify_operator_registration(join, rotation_context) + assert rotation.possession_proof != join.possession_proof + assert rotation.operator == join.operator + + +class OperatorRegistrationProofLike: + """Swaps in a foreign signature while keeping the advertised identity.""" + + def __init__(self, registration, possession_proof): + self.operator = registration.operator + self.operator_pub_key = registration.operator_pub_key + self.possession_proof = possession_proof diff --git a/tests/unit/test_release_version.py b/tests/unit/test_release_version.py new file mode 100644 index 0000000..6d3d273 --- /dev/null +++ b/tests/unit/test_release_version.py @@ -0,0 +1,63 @@ +import importlib.util +from pathlib import Path +import sys + +import pytest + + +MODULE_PATH = Path(__file__).parents[2] / "scripts" / "release_version.py" +SPEC = importlib.util.spec_from_file_location("release_version", MODULE_PATH) +assert SPEC is not None and SPEC.loader is not None +release_version = importlib.util.module_from_spec(SPEC) +sys.modules[SPEC.name] = release_version +SPEC.loader.exec_module(release_version) + + +@pytest.mark.parametrize( + ("raw", "normalized", "branch", "is_prerelease"), + [ + ("0.19.0", "0.19.0", "v0.19", False), + ("v0.19.0-rc.1", "0.19.0-rc.1", "v0.19-dev", True), + ("0.19.0rc2", "0.19.0-rc.2", "v0.19-dev", True), + ], +) +def test_release_version_normalizes_pep440_rc_spellings( + raw, normalized, branch, is_prerelease +): + version = release_version.parse_release_version(raw) + + assert version.normalized == normalized + assert version.release_branch == branch + assert version.is_prerelease is is_prerelease + + +@pytest.mark.parametrize( + ("branch", "version", "message"), + [ + ("main", "0.19.0", "not a release branch"), + ("v0.18-dev", "0.19.0-rc.1", "belongs to v0.19"), + ("v0.19", "0.19.0-rc.1", "must be cut from v0.19-dev"), + ("v0.19-dev", "0.19.0", "must be cut from v0.19"), + ], +) +def test_release_version_rejects_wrong_release_route(branch, version, message): + with pytest.raises(ValueError, match=message): + release_version.validate_branch_version(branch, version) + + +def test_release_version_accepts_rc_only_on_owning_dev_line(): + version = release_version.validate_branch_version("v0.19-dev", "0.19.0rc1") + + assert version.normalized == "0.19.0-rc.1" + + +@pytest.mark.parametrize("version", ["0.19.0-alpha.1", "0.19.0-rc.0", "00.19.0"]) +def test_release_version_rejects_non_rc_or_noncanonical_versions(version): + with pytest.raises(ValueError, match="not a supported release version"): + release_version.parse_release_version(version) + + +def test_release_tag_and_package_version_compare_after_normalization(): + assert release_version.main( + ["release_version.py", "verify-tag", "v0.19.0-rc.1", "0.19.0rc1"] + ) == 0 diff --git a/tests/unit/test_train_abi_surfaces.py b/tests/unit/test_train_abi_surfaces.py new file mode 100644 index 0000000..43f6946 --- /dev/null +++ b/tests/unit/test_train_abi_surfaces.py @@ -0,0 +1,92 @@ +import hashlib +import json + +import genlayer_py.staking as staking +from genlayer_py.consensus.abi import ( + APPEALS_ABI, + CONSENSUS_DATA_ABI, + CONSENSUS_DATA_ABI_V06, + CONSENSUS_MAIN_ABI, + CONSENSUS_MAIN_ABI_V06, +) +from genlayer_py.staking.abi import STAKING_ABI, VALIDATOR_WALLET_ABI + +# Hashes of the recursively canonicalized function surfaces generated from the +# exact consensus train artifacts at 42ea0aaf7aed9b1426681c37ee046154e22df163. +# This covers every nested tuple component, not just top-level selectors or +# function names. +EXPECTED_TRAIN_FUNCTION_SURFACE_HASHES = { + "ConsensusData": "3a7d39f4ed6c6aaa8dc1cfd5035387191f68c737ba499cd9732cf89fc97b7d34", + "ConsensusMain": "6542ed4ac55be2cdb85d190d2bc9e7e04d13a707cea9d89bde2e53feb2586ed5", + "Appeals": "7ff07eb47a1e801645e55141bcf75aaae022d46f06c8a94f29806a9fc61a0857", + "IGenLayerStaking": "1fd78e63d480800d93d41d3f5bdfd17f572bc5f394cccc7c796098f5ce8156b4", + "ValidatorWalletBlueprint": "6960726132fd77007eec8a90f036ef4be8d8efdcb6c6b79136c8835bb0b17800", +} + + +def _canonical_parameter(parameter): + canonical = { + "name": parameter.get("name", ""), + "type": parameter["type"], + } + if parameter["type"].startswith("tuple"): + canonical["components"] = [ + _canonical_parameter(component) + for component in parameter.get("components", []) + ] + return canonical + + +def _function_surface_hash(abi): + functions = [ + { + "name": entry["name"], + "stateMutability": entry.get("stateMutability"), + "inputs": [ + _canonical_parameter(parameter) for parameter in entry.get("inputs", []) + ], + "outputs": [ + _canonical_parameter(parameter) + for parameter in entry.get("outputs", []) + ], + } + for entry in abi + if entry.get("type") == "function" + ] + functions.sort( + key=lambda entry: json.dumps(entry, sort_keys=True, separators=(",", ":")) + ) + encoded = json.dumps(functions, sort_keys=True, separators=(",", ":")).encode() + return hashlib.sha256(encoded).hexdigest() + + +def test_bundled_function_surfaces_match_the_exact_consensus_train(): + bundled = { + "ConsensusData": CONSENSUS_DATA_ABI, + "ConsensusMain": CONSENSUS_MAIN_ABI, + "Appeals": APPEALS_ABI, + "IGenLayerStaking": STAKING_ABI, + "ValidatorWalletBlueprint": VALIDATOR_WALLET_ABI, + } + + assert { + name: _function_surface_hash(abi) for name, abi in bundled.items() + } == EXPECTED_TRAIN_FUNCTION_SURFACE_HASHES + + +def test_historical_consensus_abi_imports_are_train_only_aliases(): + assert CONSENSUS_DATA_ABI_V06 is CONSENSUS_DATA_ABI + assert CONSENSUS_MAIN_ABI_V06 is CONSENSUS_MAIN_ABI + + +def test_staking_package_exports_the_proof_based_join_helpers(): + expected = { + "get_validator_join_context", + "OperatorRegistrationContext", + "OperatorRegistrationProof", + "create_operator_registration", + "verify_operator_registration", + } + + assert expected.issubset(staking.__all__) + assert all(hasattr(staking, name) for name in expected) diff --git a/tests/unit/transactions/test_transaction_data_read.py b/tests/unit/transactions/test_transaction_data_read.py new file mode 100644 index 0000000..1e5b135 --- /dev/null +++ b/tests/unit/transactions/test_transaction_data_read.py @@ -0,0 +1,564 @@ +"""Train-only transaction reads use bounded surfaces at one block snapshot.""" + +from types import SimpleNamespace +from unittest.mock import Mock, call + +import genlayer_py.transactions.actions as transaction_actions +import pytest +from genlayer_py.consensus.abi import ( + CONSENSUS_DATA_ABI, + CONSENSUS_DATA_ABI_V06, + CONSENSUS_DATA_BIG_ROUNDS_ABI, + CONSENSUS_MAIN_ABI, + CONSENSUS_MAIN_ABI_V06, + ROUNDS_STORAGE_READ_ABI, + TRANSACTION_MANAGER_READ_ABI, +) +from genlayer_py.types import ( + EXECUTION_RESULT_NUMBER_TO_NAME, + VOTE_TYPE_NUMBER_TO_NAME, + ExecutionResult, + VoteType, +) +from genlayer_py.types.transactions import ( + ProtocolTransactionStatus, + ResolutionAction, + ResolutionSource, +) +from genlayer_py.chains import localnet, studio_devnet + +TX_HASH = "0x" + "ab" * 32 +CONSENSUS_DATA_ADDRESS = "0x" + "11" * 20 +ADDRESS_MANAGER_ADDRESS = "0x" + "22" * 20 +BIG_ROUNDS_ADDRESS = "0x" + "33" * 20 +TRANSACTION_MANAGER_ADDRESS = "0x" + "44" * 20 +ROUNDS_STORAGE_ADDRESS = "0x" + "55" * 20 +VALIDATORS = ["0x" + f"{index:040x}" for index in range(1, 4)] +CONSUMED_VALIDATORS = ["0x" + f"{index:040x}" for index in range(4, 6)] + + +class _Call: + def __init__(self, value, calls, name, args): + self._value = value + self._calls = calls + self._name = name + self._args = args + + def call(self, block_identifier=None): + self._calls.append((self._name, self._args, block_identifier)) + return self._value() if callable(self._value) else self._value + + +class _Contract: + def __init__(self, handlers): + self._handlers = handlers + self.calls = [] + self.functions = self + + def __getattr__(self, name): + def function(*args): + value = self._handlers[name](*args) + return _Call(value, self.calls, name, args) + + return function + + +def _light_transaction(): + return ( + 1_000, + "0x" + "66" * 20, + "0x" + "77" * 20, + 3, + 4, + 900, + 950, + bytes.fromhex("88" * 32), + 1, + bytes.fromhex("99" * 32), + b"", + b"", + [], + 0, + 2, + "0x" + "aa" * 20, + VALIDATORS[0], + 5, + bytes.fromhex("ab" * 32), + (10, 11, 12), + 0, + (0, 0, 2, 2, 0, 1, 1, len(VALIDATORS)), + len(CONSUMED_VALIDATORS), + ) + + +def _client_and_contracts(): + manager = _Contract( + { + "getAddressNonZero": lambda name: { + "ConsensusDataBigRounds": BIG_ROUNDS_ADDRESS, + "TransactionManager": TRANSACTION_MANAGER_ADDRESS, + "RoundsStorage": ROUNDS_STORAGE_ADDRESS, + }[name] + } + ) + big_rounds = _Contract( + { + "getStoredTransactionDataLight": lambda tx_id: _light_transaction(), + "getRoundValidatorsPaged": lambda tx_id, round_number, offset, limit: ( + VALIDATORS[offset : offset + limit], + len(VALIDATORS), + ), + "getConsumedValidatorsPaged": lambda tx_id, offset, limit: ( + CONSUMED_VALIDATORS[offset : offset + limit], + len(CONSUMED_VALIDATORS), + ), + } + ) + transaction_manager = _Contract( + { + "getTxExecutionResult": lambda tx_id: 1, + "getNumOfInitialValidators": lambda tx_id: 5, + } + ) + rounds_storage = _Contract( + { + "getValidatorVotes": lambda tx_id, round_number: [1, 2, 3], + "getValidatorVotesHash": lambda tx_id, round_number: [ + bytes.fromhex("01" * 32), + bytes.fromhex("02" * 32), + bytes.fromhex("03" * 32), + ], + "getValidatorResultHash": lambda tx_id, round_number: [ + bytes.fromhex("11" * 32), + bytes.fromhex("12" * 32), + bytes.fromhex("13" * 32), + ], + } + ) + resolution = ( + TX_HASH, + 5, + 6, + 6, + 1, + bytes(32), + 6, + 0, + 0, + bytes(32), + bytes(32), + 0, + 0, + 0, + 0, + bytes(32), + 0, + 1_000, + ) + latest_decision = (True, 42) + consensus_data = _Contract( + { + "addressManager": lambda: ADDRESS_MANAGER_ADDRESS, + "getTransactionLifecycle": lambda tx_id, timestamp: ( + 5, + resolution, + latest_decision, + True, + ), + "canFinalize": lambda tx_id, timestamp, decision_id: (True, 1_000, 999), + } + ) + contracts = { + CONSENSUS_DATA_ADDRESS: consensus_data, + ADDRESS_MANAGER_ADDRESS: manager, + BIG_ROUNDS_ADDRESS: big_rounds, + TRANSACTION_MANAGER_ADDRESS: transaction_manager, + ROUNDS_STORAGE_ADDRESS: rounds_storage, + } + eth = SimpleNamespace( + block_number=123, + contract=lambda address, abi: contracts[address], + ) + client = SimpleNamespace( + chain=SimpleNamespace( + id=4221, + consensus_data_contract={ + "address": CONSENSUS_DATA_ADDRESS, + "abi": [], + }, + ), + w3=SimpleNamespace(eth=eth), + ) + return client, contracts + + +def test_train_transaction_read_composes_light_and_split_array_surfaces(monkeypatch): + client, contracts = _client_and_contracts() + monkeypatch.setattr(transaction_actions, "TRANSACTION_ARRAY_PAGE_SIZE", 2) + + result = transaction_actions._read_train_transaction_data( + client, + contracts[CONSENSUS_DATA_ADDRESS], + TX_HASH, + 123, + ) + + ( + tx_data, + validators, + votes, + vote_hashes, + result_hashes, + consumed_validators, + execution_result, + num_of_initial_validators, + ) = result + assert tx_data == _light_transaction() + assert validators == VALIDATORS + assert votes == [1, 2, 3] + assert vote_hashes[0] == bytes.fromhex("01" * 32) + assert result_hashes[0] == bytes.fromhex("11" * 32) + assert consumed_validators == CONSUMED_VALIDATORS + assert execution_result == 1 + assert num_of_initial_validators == 5 + assert [ + call[1][2] + for call in contracts[BIG_ROUNDS_ADDRESS].calls + if call[0] == "getRoundValidatorsPaged" + ] == [0, 2] + assert [ + call[1][1] + for call in contracts[BIG_ROUNDS_ADDRESS].calls + if call[0] == "getConsumedValidatorsPaged" + ] == [0] + assert all( + block == 123 + for contract in contracts.values() + for _, _, block in contract.calls + ) + assert not any( + name == "getTransactionAllData" + for contract in contracts.values() + for name, _, _ in contract.calls + ) + + +def test_get_transaction_exposes_only_stored_consumer_lifecycle(monkeypatch): + client, contracts = _client_and_contracts() + monkeypatch.setattr( + transaction_actions, "_decode_triggered_txs", lambda self, tx: [] + ) + + result = transaction_actions.get_transaction(client, TX_HASH) + + assert result["lifecycle"] == {"state": "decided", "outcome": "accepted"} + assert "status" not in result + assert "status_name" not in result + assert "stored_status" not in result + assert "resolution_action" not in result + assert "can_finalize" not in result + assert result["last_round"]["round_validators"] == VALIDATORS + assert result["last_round"]["validator_votes"] == [1, 2, 3] + assert result["last_round"]["validator_result_hash"] == [ + "0x" + "11" * 32, + "0x" + "12" * 32, + "0x" + "13" * 32, + ] + assert result["consumed_validators"] == CONSUMED_VALIDATORS + assert result["tx_execution_hash"] == "0x" + "99" * 32 + assert result["tx_receipt"] is None + assert result["tx_execution_result_name"] == "FINISHED_WITH_RETURN" + assert result["num_of_initial_validators"] == "5" + assert result["initial_rotations"] == "3" + + lifecycle_calls = contracts[CONSENSUS_DATA_ADDRESS].calls + assert not any(call[0] == "getTransactionLifecycle" for call in lifecycle_calls) + assert not any(call[0] == "canFinalize" for call in lifecycle_calls) + + +def test_advanced_transaction_lifecycle_keeps_projection_explicit(): + client, contracts = _client_and_contracts() + + result = transaction_actions.get_transaction_lifecycle(client, TX_HASH) + + assert result == { + "stored_status": 5, + "stored_status_name": ProtocolTransactionStatus.ACCEPTED, + "projected_status": 6, + "projected_status_name": ProtocolTransactionStatus.UNDETERMINED, + "resolution_action": 6, + "resolution_action_name": ResolutionAction.FINALIZE, + "resolution_source": 6, + "resolution_source_name": ResolutionSource.FULL_REVEAL, + "decision_id": "42", + "decision_active": True, + "evaluated_at": 1_000, + } + lifecycle_calls = contracts[CONSENSUS_DATA_ADDRESS].calls + assert ("getTransactionLifecycle", (TX_HASH, 0), 123) in lifecycle_calls + assert not any(call[0] == "canFinalize" for call in lifecycle_calls) + + +@pytest.mark.parametrize("chain_id", [localnet.id, studio_devnet.id]) +def test_studio_transaction_lifecycle_decodes_the_exact_node_rpc_schema(chain_id): + provider = Mock() + provider.make_request.return_value = { + "result": { + "storedStatus": "Accepted", + "storedStatusCode": 5, + "projectedStatus": "Undetermined", + "projectedStatusCode": 6, + "resolutionAction": "Finalize", + "resolutionActionCode": 6, + "resolutionSource": "FullReveal", + "resolutionSourceCode": 6, + "decisionId": "42", + "decisionActive": True, + "evaluatedAt": 1_000, + } + } + client = SimpleNamespace( + chain=SimpleNamespace(id=chain_id), + provider=provider, + ) + + result = transaction_actions.get_transaction_lifecycle( + client, bytes.fromhex("ab" * 32), timestamp=999 + ) + + assert result == { + "stored_status": 5, + "stored_status_name": ProtocolTransactionStatus.ACCEPTED, + "projected_status": 6, + "projected_status_name": ProtocolTransactionStatus.UNDETERMINED, + "resolution_action": 6, + "resolution_action_name": ResolutionAction.FINALIZE, + "resolution_source": 6, + "resolution_source_name": ResolutionSource.FULL_REVEAL, + "decision_id": "42", + "decision_active": True, + "evaluated_at": 1_000, + } + provider.make_request.assert_called_once_with( + method="gen_getTransactionLifecycle", + params=[{"txId": TX_HASH, "timestamp": 999}], + ) + + +def test_local_transaction_lifecycle_rejects_code_name_drift(): + provider = Mock() + provider.make_request.return_value = { + "result": { + "storedStatus": "Finalized", + "storedStatusCode": 5, + "projectedStatus": "Undetermined", + "projectedStatusCode": 6, + "resolutionAction": "Finalize", + "resolutionActionCode": 6, + "resolutionSource": "FullReveal", + "resolutionSourceCode": 6, + "decisionId": None, + "decisionActive": False, + "evaluatedAt": 1_000, + } + } + client = SimpleNamespace( + chain=SimpleNamespace(id=localnet.id), + provider=provider, + ) + + with pytest.raises(transaction_actions.GenLayerError, match="storedStatus"): + transaction_actions.get_transaction_lifecycle(client, TX_HASH) + + +def test_local_transaction_lifecycle_uses_stored_status_when_rpc_is_absent(): + provider = Mock() + provider.make_request.side_effect = [ + {"error": {"code": -32601, "message": "Method not found"}}, + {"result": {"status": "ACCEPTED"}}, + ] + client = SimpleNamespace( + chain=SimpleNamespace(id=localnet.id), + provider=provider, + ) + + result = transaction_actions.get_transaction_lifecycle( + client, bytes.fromhex("ab" * 32), timestamp=999 + ) + + assert result == { + "stored_status": 5, + "stored_status_name": ProtocolTransactionStatus.ACCEPTED, + "projected_status": 5, + "projected_status_name": ProtocolTransactionStatus.ACCEPTED, + "resolution_action": 0, + "resolution_action_name": ResolutionAction.NO_OP, + "resolution_source": 0, + "resolution_source_name": ResolutionSource.UNSPECIFIED, + "decision_id": None, + "decision_active": False, + "evaluated_at": 999, + } + assert provider.make_request.call_args_list == [ + call( + method="gen_getTransactionLifecycle", + params=[{"txId": TX_HASH, "timestamp": 999}], + ), + call(method="eth_getTransactionByHash", params=[TX_HASH]), + ] + + +def test_local_transaction_lifecycle_maps_activated_to_pending(): + provider = Mock() + provider.make_request.side_effect = [ + {"error": {"code": -32601, "message": "Method not found"}}, + {"result": {"status": "ACTIVATED"}}, + ] + client = SimpleNamespace( + chain=SimpleNamespace(id=localnet.id), + provider=provider, + ) + + result = transaction_actions.get_transaction_lifecycle(client, TX_HASH) + + assert result["stored_status_name"] == ProtocolTransactionStatus.PENDING + assert result["projected_status_name"] == ProtocolTransactionStatus.PENDING + assert result["decision_active"] is False + + +def test_local_transaction_lifecycle_does_not_hide_real_rpc_failures(): + provider = Mock() + provider.make_request.return_value = { + "error": {"code": -32000, "message": "execution reverted"} + } + client = SimpleNamespace( + chain=SimpleNamespace(id=localnet.id), + provider=provider, + ) + + with pytest.raises(transaction_actions.GenLayerError, match="execution reverted"): + transaction_actions.get_transaction_lifecycle(client, TX_HASH) + + provider.make_request.assert_called_once() + + +def test_packaged_consensus_abis_expose_only_the_train_lifecycle_signature(): + for abi in (CONSENSUS_DATA_ABI, CONSENSUS_DATA_ABI_V06): + functions = { + entry["name"]: entry for entry in abi if entry.get("type") == "function" + } + assert "getTransactionData" not in functions + assert "getStoredTransactionData" in functions + assert "getTransactionLifecycle" in functions + assert len(functions["canFinalize"]["inputs"]) == 3 + transaction_components = functions["getTransactionAllData"]["outputs"][0][ + "components" + ] + assert transaction_components[2]["name"] == "status" + assert transaction_components[-1]["name"] == "queueContext" + + big_round_functions = { + entry["name"] + for entry in CONSENSUS_DATA_BIG_ROUNDS_ABI + if entry.get("type") == "function" + } + + for abi in (CONSENSUS_MAIN_ABI, CONSENSUS_MAIN_ABI_V06): + functions = { + entry["name"]: entry for entry in abi if entry.get("type") == "function" + } + assert [item["type"] for item in functions["addTransaction"]["inputs"]] == [ + "tuple" + ] + assert [item["type"] for item in functions["deploySalted"]["inputs"]] == [ + "tuple" + ] + assert [item["type"] for item in functions["topUpFees"]["inputs"]] == [ + "bytes32", + "tuple", + ] + assert [ + item["type"] for item in functions["topUpAndSubmitAppeal"]["inputs"] + ] == ["bytes32", "uint256", "tuple"] + assert [item["type"] for item in functions["submitAppeal"]["inputs"]] == [ + "bytes32", + "uint256", + ] + assert [ + item["type"] for item in functions["finalizeTransaction"]["inputs"] + ] == ["bytes32", "uint256"] + add_params = functions["addTransaction"]["inputs"][0]["components"] + assert [item["type"] for item in add_params] == [ + "address", + "address", + "uint256", + "uint256", + "uint256", + "uint256", + "uint256", + "tuple", + "bytes", + "tuple[]", + ] + assert [item["type"] for item in add_params[7]["components"]] == [ + "uint256", + "uint256", + "uint256", + "uint256", + "uint256", + "uint256", + "uint256[]", + "uint256", + "uint256", + "uint256", + ] + assert [item["type"] for item in add_params[9]["components"]] == [ + "uint8", + "bool", + "uint256", + "address", + "bytes32", + "uint256", + "bytes", + ] + assert big_round_functions == { + "getStoredTransactionDataLight", + "getRoundValidatorsPaged", + "getConsumedValidatorsPaged", + } + + rounds_storage_functions = { + entry["name"] + for entry in ROUNDS_STORAGE_READ_ABI + if entry.get("type") == "function" + } + assert rounds_storage_functions == { + "getValidatorVotes", + "getValidatorVotesHash", + "getValidatorResultHash", + } + + transaction_manager_functions = { + entry["name"] + for entry in TRANSACTION_MANAGER_READ_ABI + if entry.get("type") == "function" + } + assert transaction_manager_functions == { + "getTxExecutionResult", + "getNumOfInitialValidators", + } + + +def test_train_vote_and_execution_enums_cover_every_contract_ordinal(): + expected = { + "0": VoteType.NOT_VOTED, + "1": VoteType.FINISHED_WITH_RETURN, + "2": VoteType.FINISHED_WITH_ERROR, + "3": VoteType.TIMEOUT, + "4": VoteType.NONDET_DISAGREE, + "5": VoteType.DETERMINISTIC_VIOLATION, + } + assert VOTE_TYPE_NUMBER_TO_NAME == expected + assert EXECUTION_RESULT_NUMBER_TO_NAME == { + ordinal: ExecutionResult(member.value) for ordinal, member in expected.items() + } diff --git a/tests/unit/transactions/test_transaction_lifecycle.py b/tests/unit/transactions/test_transaction_lifecycle.py new file mode 100644 index 0000000..7efba8b --- /dev/null +++ b/tests/unit/transactions/test_transaction_lifecycle.py @@ -0,0 +1,124 @@ +import genlayer_py +import genlayer_py.types as public_types +import pytest +from types import SimpleNamespace + +from genlayer_py.chains import localnet +from genlayer_py.transactions.actions import get_transaction +from genlayer_py.types.transactions import ( + CanceledTransactionLifecycle, + DecidedTransactionLifecycle, + FinalizedTransactionLifecycle, + ProcessingTransactionLifecycle, + PROTOCOL_TRANSACTION_STATUS_NUMBER_TO_NAME, + ProtocolTransactionStatus, + ResolutionAction, + ResolutionSource, + transaction_lifecycle_from_protocol_status, + transaction_outcome_from_protocol_result, +) + +EXPECTED_LIFECYCLES = { + 0: {"state": "processing", "phase": "uninitialized"}, + 1: {"state": "processing", "phase": "pending"}, + 2: {"state": "processing", "phase": "proposing"}, + 3: {"state": "processing", "phase": "committing"}, + 4: {"state": "processing", "phase": "revealing"}, + 5: {"state": "decided", "outcome": "accepted"}, + 6: {"state": "decided", "outcome": "undetermined"}, + 7: {"state": "finalized"}, + 8: {"state": "canceled"}, + 9: {"state": "processing", "phase": "appeal_revealing"}, + 10: {"state": "processing", "phase": "appeal_committing"}, + 11: {"state": "decided", "outcome": "validators_timeout"}, + 12: {"state": "decided", "outcome": "leader_timeout"}, + 13: {"state": "processing", "phase": "leader_revealing"}, +} + + +@pytest.mark.parametrize("protocol_status, expected", EXPECTED_LIFECYCLES.items()) +def test_every_protocol_status_has_one_public_lifecycle(protocol_status, expected): + assert transaction_lifecycle_from_protocol_status(protocol_status) == expected + assert transaction_lifecycle_from_protocol_status(str(protocol_status)) == expected + assert ( + transaction_lifecycle_from_protocol_status( + PROTOCOL_TRANSACTION_STATUS_NUMBER_TO_NAME[str(protocol_status)] + ) + == expected + ) + + +@pytest.mark.parametrize("value", [-1, 14, "unknown"]) +def test_unknown_or_removed_protocol_status_is_rejected(value): + with pytest.raises(ValueError, match="Unknown protocol transaction status"): + transaction_lifecycle_from_protocol_status(value) + + +def test_public_lifecycle_is_a_discriminated_union(): + assert ProcessingTransactionLifecycle.__required_keys__ == {"state", "phase"} + assert DecidedTransactionLifecycle.__required_keys__ == {"state", "outcome"} + assert FinalizedTransactionLifecycle.__required_keys__ == {"state"} + assert FinalizedTransactionLifecycle.__optional_keys__ == {"outcome"} + assert CanceledTransactionLifecycle.__required_keys__ == {"state"} + + +@pytest.mark.parametrize( + "protocol_result, expected", + [ + (0, None), + (1, "accepted"), + (2, "undetermined"), + (3, "validators_timeout"), + (4, "undetermined"), + (5, "undetermined"), + ], +) +def test_finalized_outcome_is_added_only_when_the_result_proves_it( + protocol_result, expected +): + assert transaction_outcome_from_protocol_result(protocol_result) == expected + + +def test_raw_protocol_types_are_advanced_only(): + assert not hasattr(genlayer_py, "ResolutionAction") + assert not hasattr(genlayer_py, "ProtocolTransactionStatus") + assert not hasattr(public_types, "ResolutionAction") + assert not hasattr(public_types, "ResolutionSource") + assert not hasattr(public_types, "ProtocolTransactionStatus") + assert len(ProtocolTransactionStatus) == 14 + assert len(ResolutionSource) == 12 + assert ResolutionAction.FINALIZE.value == "Finalize" + + +@pytest.mark.parametrize( + "raw_transaction, expected", + [ + ( + {"status": "ACTIVATED", "data": None}, + {"state": "processing", "phase": "pending"}, + ), + ( + { + "status": "FINALIZED", + "result_name": "MAJORITY_AGREE", + "data": None, + }, + {"state": "finalized", "outcome": "accepted"}, + ), + ], +) +def test_local_transaction_runtime_exposes_only_public_lifecycle( + raw_transaction, expected +): + client = SimpleNamespace( + chain=SimpleNamespace(id=localnet.id), + provider=SimpleNamespace( + make_request=lambda method, params: {"result": dict(raw_transaction)} + ), + ) + + transaction = get_transaction(client, "0x" + "ab" * 32) + + assert transaction["lifecycle"] == expected + assert "status" not in transaction + assert "status_name" not in transaction diff --git a/tests/unit/transactions/test_wait_for_transaction_receipt.py b/tests/unit/transactions/test_wait_for_transaction_receipt.py index 2a06893..48d4518 100644 --- a/tests/unit/transactions/test_wait_for_transaction_receipt.py +++ b/tests/unit/transactions/test_wait_for_transaction_receipt.py @@ -1,230 +1,162 @@ import pytest from unittest.mock import patch from genlayer_py.transactions.actions import ( + wait_for_decision, + wait_for_finalization, wait_for_transaction_receipt, _simplify_transaction_receipt, + is_successful, ) -from genlayer_py.types import TransactionStatus, DECIDED_STATES, is_decided_state +from genlayer_py.types import ExecutionResult from genlayer_py.exceptions import GenLayerError +TX_HASH = "0x4b8037744adab7ea8335b4f839979d20031d83a8ccdf706e0ae61312930335f6" -class TestWaitForTransactionReceipt: - """Test suite for wait_for_transaction_receipt function""" - def test_wait_for_finalized_transaction_success( - self, mock_client, full_write_transaction_data - ): - """Test successful wait for finalized transaction""" - mock_client.get_transaction.return_value = full_write_transaction_data - - result = wait_for_transaction_receipt( - self=mock_client, - transaction_hash="0x4b8037744adab7ea8335b4f839979d20031d83a8ccdf706e0ae61312930335f6", - status=TransactionStatus.FINALIZED, - full_transaction=True, - ) +def _transaction(lifecycle, **extra): + return {"hash": TX_HASH, "lifecycle": lifecycle, **extra} - assert result == full_write_transaction_data - mock_client.get_transaction.assert_called_once() - def test_wait_for_accepted_transaction_with_finalized_status( - self, mock_client, full_write_transaction_data +class TestTransactionWaits: + @pytest.mark.parametrize( + "lifecycle", + [ + {"state": "decided", "outcome": "accepted"}, + {"state": "decided", "outcome": "undetermined"}, + {"state": "decided", "outcome": "validators_timeout"}, + {"state": "decided", "outcome": "leader_timeout"}, + {"state": "finalized"}, + {"state": "canceled"}, + ], + ) + def test_wait_for_decision_uses_materialized_lifecycle( + self, mock_client, lifecycle ): - """Test that ACCEPTED status accepts FINALIZED transactions""" - mock_client.get_transaction.return_value = full_write_transaction_data - - result = wait_for_transaction_receipt( - self=mock_client, - transaction_hash="0x4b8037744adab7ea8335b4f839979d20031d83a8ccdf706e0ae61312930335f6", - status=TransactionStatus.ACCEPTED, # Requesting ACCEPTED - full_transaction=True, + transaction = _transaction(lifecycle) + mock_client.get_transaction.return_value = transaction + + assert ( + wait_for_decision(mock_client, TX_HASH, full_transaction=True) + == transaction ) - # Should accept FINALIZED (status 7) when requesting ACCEPTED - assert result == full_write_transaction_data + def test_wait_for_finalization_ignores_nonfinal_stored_state(self, mock_client): + processing = _transaction({"state": "processing", "phase": "pending"}) + decided = _transaction({"state": "decided", "outcome": "accepted"}) + finalized = _transaction({"state": "finalized"}) + mock_client.get_transaction.side_effect = [processing, decided, finalized] - def test_wait_for_transaction_with_simplified_receipt( - self, mock_client, full_write_transaction_data - ): - """Test wait for transaction with simplified receipt (full_transaction=False)""" - mock_client.get_transaction.return_value = full_write_transaction_data + with patch("time.sleep") as sleep: + result = wait_for_finalization( + mock_client, TX_HASH, interval=100, full_transaction=True + ) + + assert result == finalized + assert mock_client.get_transaction.call_count == 3 + assert sleep.call_count == 2 + sleep.assert_called_with(0.1) + + def test_receipt_default_waits_for_decision_and_simplifies(self, mock_client): + transaction = _transaction({"state": "decided", "outcome": "accepted"}) + mock_client.get_transaction.return_value = transaction + simplified = {"hash": TX_HASH, "lifecycle": transaction["lifecycle"]} with patch( - "genlayer_py.transactions.actions._simplify_transaction_receipt" - ) as mock_simplify: - simplified_data = {"hash": "0x123", "status": 7, "simplified": True} - mock_simplify.return_value = simplified_data - - result = wait_for_transaction_receipt( - self=mock_client, - transaction_hash="0x4b8037744adab7ea8335b4f839979d20031d83a8ccdf706e0ae61312930335f6", - full_transaction=False, - ) + "genlayer_py.transactions.actions._simplify_transaction_receipt", + return_value=simplified, + ) as simplify: + result = wait_for_transaction_receipt(mock_client, TX_HASH) - mock_simplify.assert_called_once_with(full_write_transaction_data) - assert result == simplified_data + assert result == simplified + simplify.assert_called_once_with(transaction) - def test_wait_for_transaction_timeout(self, mock_client, pending_transaction_data): - """Test timeout when transaction doesn't reach desired status""" - mock_client.get_transaction.return_value = pending_transaction_data + def test_receipt_can_wait_for_finalization(self, mock_client): + transaction = _transaction({"state": "finalized"}) + mock_client.get_transaction.return_value = transaction - with pytest.raises(GenLayerError, match="did not reach desired status"): + assert ( wait_for_transaction_receipt( - self=mock_client, - transaction_hash="0x4b8037744adab7ea8335b4f839979d20031d83a8ccdf706e0ae61312930335f6", - retries=2, - interval=1, # 1ms for fast test + mock_client, + TX_HASH, + wait_until="finalized", + full_transaction=True, ) + == transaction + ) + + def test_processing_timeout_reports_public_phase(self, mock_client): + mock_client.get_transaction.return_value = _transaction( + {"state": "processing", "phase": "leader_revealing"} + ) - # Should have tried 2 times - assert mock_client.get_transaction.call_count == 2 + with pytest.raises( + GenLayerError, match="Last observed lifecycle state: 'processing'" + ): + wait_for_decision(mock_client, TX_HASH, retries=1, interval=1) - def test_wait_for_nonexistent_transaction(self, mock_client): - """Test error when transaction doesn't exist""" + def test_wait_for_finalization_fails_fast_when_canceled(self, mock_client): + mock_client.get_transaction.return_value = _transaction({"state": "canceled"}) + + with pytest.raises(GenLayerError, match="canceled before finalization"): + wait_for_finalization(mock_client, TX_HASH) + + mock_client.get_transaction.assert_called_once() + + def test_nonexistent_transaction(self, mock_client): mock_client.get_transaction.return_value = None with pytest.raises(GenLayerError, match="Transaction .* not found"): - wait_for_transaction_receipt( - self=mock_client, - transaction_hash="0x4b8037744adab7ea8335b4f839979d20031d83a8ccdf706e0ae61312930335f6", - ) + wait_for_decision(mock_client, TX_HASH) - @patch("time.sleep") - def test_wait_for_transaction_with_retry_logic( - self, - mock_sleep, - mock_client, - pending_transaction_data, - full_write_transaction_data, - ): - """Test retry logic with eventual success""" - # First two calls return pending, third returns finalized - mock_client.get_transaction.side_effect = [ - pending_transaction_data, - pending_transaction_data, - full_write_transaction_data, - ] + def test_invalid_lifecycle_is_rejected(self, mock_client): + mock_client.get_transaction.return_value = {"hash": TX_HASH} - result = wait_for_transaction_receipt( - self=mock_client, - transaction_hash="0x4b8037744adab7ea8335b4f839979d20031d83a8ccdf706e0ae61312930335f6", - interval=100, # 100ms - full_transaction=True, - ) + with pytest.raises(GenLayerError, match="has no valid lifecycle"): + wait_for_decision(mock_client, TX_HASH) - assert result == full_write_transaction_data - assert mock_client.get_transaction.call_count == 3 - assert mock_sleep.call_count == 2 - mock_sleep.assert_called_with(0.1) # 100ms / 1000 + def test_invalid_receipt_wait_target_is_rejected(self, mock_client): + with pytest.raises(ValueError, match="wait_until"): + wait_for_transaction_receipt(mock_client, TX_HASH, wait_until="projected") - def test_wait_for_transaction_with_custom_parameters( - self, mock_client, full_write_transaction_data - ): - """Test with custom interval and retries""" - mock_client.get_transaction.return_value = full_write_transaction_data - - result = wait_for_transaction_receipt( - self=mock_client, - transaction_hash="0x4b8037744adab7ea8335b4f839979d20031d83a8ccdf706e0ae61312930335f6", - status=TransactionStatus.FINALIZED, - interval=500, - retries=10, - full_transaction=True, - ) - assert result == full_write_transaction_data - - def test_wait_for_accepted_with_all_decided_states(self, mock_client): - """Test that ACCEPTED status accepts all decided states""" - decided_statuses = ["5", "6", "8", "7", "12", "13"] # ACCEPTED, UNDETERMINED, CANCELED, FINALIZED, VALIDATORS_TIMEOUT, LEADER_TIMEOUT - - for status_num in decided_statuses: - mock_transaction = { - "hash": "0x4b8037744adab7ea8335b4f839979d20031d83a8ccdf706e0ae61312930335f6", - "status": status_num, - "status_name": "test_status", - "from_address": "0x123", - "to_address": "0x456", - "value": "0", - "gaslimit": "1000000", - "nonce": "1", - "created_at": "2023-01-01T00:00:00Z", +class TestIsSuccessful: + def test_truth_table(self): + assert is_successful( + { + "lifecycle": {"state": "decided", "outcome": "accepted"}, + "tx_execution_result": "1", + } + ) + assert not is_successful( + { + "lifecycle": {"state": "decided", "outcome": "undetermined"}, + "tx_execution_result": "1", + } + ) + assert not is_successful( + { + "lifecycle": {"state": "decided", "outcome": "accepted"}, + "tx_execution_result": "2", + } + ) + assert is_successful( + { + "lifecycle": {"state": "finalized"}, + "tx_execution_result_name": ExecutionResult.FINISHED_WITH_RETURN, + } + ) + assert is_successful( + { + "lifecycle": {"state": "finalized", "outcome": "accepted"}, + "tx_execution_result_name": ExecutionResult.FINISHED_WITH_RETURN, + } + ) + assert not is_successful( + { + "lifecycle": {"state": "finalized", "outcome": "undetermined"}, + "tx_execution_result_name": ExecutionResult.FINISHED_WITH_RETURN, } - - mock_client.get_transaction.return_value = mock_transaction - - result = wait_for_transaction_receipt( - self=mock_client, - transaction_hash="0x4b8037744adab7ea8335b4f839979d20031d83a8ccdf706e0ae61312930335f6", - status=TransactionStatus.ACCEPTED, - full_transaction=True, - ) - - assert result == mock_transaction - - def test_wait_for_specific_status_not_affected(self, mock_client): - """Test that waiting for specific non-ACCEPTED statuses is not affected by decided states logic""" - mock_transaction = { - "hash": "0x4b8037744adab7ea8335b4f839979d20031d83a8ccdf706e0ae61312930335f6", - "status": "7", # FINALIZED - "status_name": "FINALIZED", - "from_address": "0x123", - "to_address": "0x456", - "value": "0", - "gaslimit": "1000000", - "nonce": "1", - "created_at": "2023-01-01T00:00:00Z", - } - - mock_client.get_transaction.return_value = mock_transaction - - result = wait_for_transaction_receipt( - self=mock_client, - transaction_hash="0x4b8037744adab7ea8335b4f839979d20031d83a8ccdf706e0ae61312930335f6", - status=TransactionStatus.FINALIZED, - full_transaction=True, ) - - assert result == mock_transaction - - -class TestDecidedStatesUtility: - """Test suite for DECIDED_STATES constant and is_decided_state function""" - - def test_decided_states_constant(self): - """Test that DECIDED_STATES contains all expected states""" - expected_states = [ - TransactionStatus.ACCEPTED, - TransactionStatus.UNDETERMINED, - TransactionStatus.LEADER_TIMEOUT, - TransactionStatus.VALIDATORS_TIMEOUT, - TransactionStatus.CANCELED, - TransactionStatus.FINALIZED - ] - - assert DECIDED_STATES == expected_states - - def test_is_decided_state_with_decided_statuses(self): - """Test is_decided_state returns True for all decided statuses""" - decided_status_numbers = ["5", "6", "8", "7", "12", "13"] # ACCEPTED, UNDETERMINED, CANCELED, FINALIZED, VALIDATORS_TIMEOUT, LEADER_TIMEOUT - - for status_num in decided_status_numbers: - assert is_decided_state(status_num) == True, f"Status {status_num} should be decided" - - def test_is_decided_state_with_non_decided_statuses(self): - """Test is_decided_state returns False for non-decided statuses""" - non_decided_status_numbers = ["0", "1", "2", "3", "4", "9", "10", "11"] # UNINITIALIZED, PENDING, PROPOSING, COMMITTING, REVEALING, APPEAL_REVEALING, APPEAL_COMMITTING, READY_TO_FINALIZE - - for status_num in non_decided_status_numbers: - assert is_decided_state(status_num) == False, f"Status {status_num} should not be decided" - - def test_is_decided_state_with_invalid_status(self): - """Test is_decided_state returns False for invalid statuses""" - invalid_statuses = ["999", "invalid", "", None] - - for status in invalid_statuses: - if status is not None: - assert is_decided_state(status) == False, f"Invalid status {status} should not be decided" class TestSimplifyTransactionReceipt: @@ -265,8 +197,7 @@ def test_simplify_preserves_essential_fields(self, full_write_transaction_data): # These fields should be preserved essential_fields = [ "hash", - "status", - "status_name", + "lifecycle", "from_address", "to_address", "value", diff --git a/tests/unit/vesting/__init__.py b/tests/unit/vesting/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit/vesting/test_vesting_actions.py b/tests/unit/vesting/test_vesting_actions.py new file mode 100644 index 0000000..68be07e --- /dev/null +++ b/tests/unit/vesting/test_vesting_actions.py @@ -0,0 +1,559 @@ +"""Unit tests for the vesting action module. + +The tests here are structural, matching the staking action tests: write +helpers are checked for ABI selectors and target addresses, while read +helpers use mocked contract calls instead of a live node. +""" + +from types import SimpleNamespace +from unittest.mock import Mock + +from eth_utils import keccak +import pytest +from web3 import Web3 + +import genlayer_py.vesting.actions as vesting_actions +from genlayer_py.vesting.abi import VESTING_ABI + + +VESTING_ADDR = "0x1111111111111111111111111111111111111111" +FACTORY_ADDR = "0x2222222222222222222222222222222222222222" +SENDER_ADDR = "0x3333333333333333333333333333333333333333" +VALIDATOR_ADDR = "0x4444444444444444444444444444444444444444" +BENEFICIARY_ADDR = "0x5555555555555555555555555555555555555555" +CREATOR_ADDR = "0x6666666666666666666666666666666666666666" +REVOKER_ADDR = "0x7777777777777777777777777777777777777777" +WALLET_ADDR = "0x8888888888888888888888888888888888888888" +NEW_OPERATOR_ADDR = "0x9999999999999999999999999999999999999999" + +SEL_VESTING_DELEGATOR_JOIN = keccak( + text="vestingDelegatorJoin(address,uint256)" +)[:4].hex() +SEL_VESTING_DELEGATOR_EXIT = keccak( + text="vestingDelegatorExit(address,uint256)" +)[:4].hex() +SEL_VESTING_DELEGATOR_CLAIM = keccak(text="vestingDelegatorClaim(address)")[ + :4 +].hex() +SEL_VESTING_VALIDATOR_JOIN = keccak( + text="vestingValidatorJoin(address,uint256)" +)[:4].hex() +SEL_VESTING_VALIDATOR_DEPOSIT = keccak( + text="vestingValidatorDeposit(address,uint256)" +)[:4].hex() +SEL_VESTING_VALIDATOR_EXIT = keccak( + text="vestingValidatorExit(address,uint256)" +)[:4].hex() +SEL_VESTING_VALIDATOR_CLAIM = keccak(text="vestingValidatorClaim(address)")[ + :4 +].hex() +SEL_VESTING_VALIDATOR_INITIATE_OPERATOR_TRANSFER = keccak( + text="vestingValidatorInitiateOperatorTransfer(address,address)" +)[:4].hex() +SEL_VESTING_VALIDATOR_COMPLETE_OPERATOR_TRANSFER = keccak( + text="vestingValidatorCompleteOperatorTransfer(address)" +)[:4].hex() +SEL_VESTING_VALIDATOR_CANCEL_OPERATOR_TRANSFER = keccak( + text="vestingValidatorCancelOperatorTransfer(address)" +)[:4].hex() +SEL_VESTING_VALIDATOR_SET_IDENTITY = keccak( + text=( + "vestingValidatorSetIdentity(" + "address,string,string,string,string,string,string,string,string,bytes)" + ) +)[:4].hex() +SEL_VESTING_WITHDRAW = keccak(text="vestingWithdraw(uint256)")[:4].hex() + + +def _make_client(): + """SimpleNamespace stand-in for GenLayerClient. + + Uses a real Web3().eth for contract encoding, but patches the eth + methods that would otherwise hit a live node. + """ + signed = SimpleNamespace(raw_transaction=b"\x00") + w3 = Web3() + w3.eth.get_transaction_count = Mock(return_value=1) + w3.eth.estimate_gas = Mock(return_value=100_000) + w3.eth.send_raw_transaction = Mock(return_value=b"\xde\xad" * 16) + type(w3.eth).gas_price = 1_000_000_000 # type: ignore[assignment] + + local_account = SimpleNamespace( + address=SENDER_ADDR, + sign_transaction=Mock(return_value=signed), + ) + chain = SimpleNamespace(id=61999) + return SimpleNamespace(chain=chain, local_account=local_account, w3=w3) + + +def _last_tx(client): + """Return the tx dict the client's sign_transaction was called with.""" + return client.local_account.sign_transaction.call_args.args[0] + + +def _call_result(value): + return SimpleNamespace(call=Mock(return_value=value)) + + +def _decode_vesting_tx(client, data): + contract = client.w3.eth.contract( + address=client.w3.to_checksum_address(VESTING_ADDR), abi=VESTING_ABI + ) + return contract.decode_function_input(data) + + +def test_vesting_delegator_join_targets_vesting_contract(): + client = _make_client() + vesting_actions.vesting_delegator_join( + self=client, + vesting_contract_address=VESTING_ADDR, + validator=VALIDATOR_ADDR, + amount=10, + ) + tx = _last_tx(client) + assert tx["to"].lower() == VESTING_ADDR.lower() + assert tx["value"] == 0 + assert tx["data"][2:10] == SEL_VESTING_DELEGATOR_JOIN + + +def test_vesting_delegator_exit_targets_vesting_contract(): + client = _make_client() + vesting_actions.vesting_delegator_exit( + self=client, + vesting_contract_address=VESTING_ADDR, + validator=VALIDATOR_ADDR, + shares=42, + ) + tx = _last_tx(client) + assert tx["to"].lower() == VESTING_ADDR.lower() + assert tx["data"][2:10] == SEL_VESTING_DELEGATOR_EXIT + + +def test_vesting_delegator_claim_targets_vesting_contract(): + client = _make_client() + vesting_actions.vesting_delegator_claim( + self=client, + vesting_contract_address=VESTING_ADDR, + validator=VALIDATOR_ADDR, + ) + tx = _last_tx(client) + assert tx["to"].lower() == VESTING_ADDR.lower() + assert tx["data"][2:10] == SEL_VESTING_DELEGATOR_CLAIM + + +def test_vesting_withdraw_targets_vesting_contract(): + client = _make_client() + vesting_actions.vesting_withdraw( + self=client, + vesting_contract_address=VESTING_ADDR, + amount=7, + ) + tx = _last_tx(client) + assert tx["to"].lower() == VESTING_ADDR.lower() + assert tx["data"][2:10] == SEL_VESTING_WITHDRAW + + +def test_vesting_validator_join_targets_vesting_contract(): + client = _make_client() + vesting_actions.vesting_validator_join( + self=client, + vesting_contract_address=VESTING_ADDR, + operator=VALIDATOR_ADDR, + amount=10, + ) + tx = _last_tx(client) + assert tx["to"].lower() == VESTING_ADDR.lower() + assert tx["value"] == 0 + assert tx["data"][2:10] == SEL_VESTING_VALIDATOR_JOIN + + +def test_vesting_validator_deposit_targets_vesting_contract(): + client = _make_client() + vesting_actions.vesting_validator_deposit( + self=client, + vesting_contract_address=VESTING_ADDR, + wallet=WALLET_ADDR, + amount=25, + ) + tx = _last_tx(client) + assert tx["to"].lower() == VESTING_ADDR.lower() + assert tx["value"] == 0 + assert tx["data"][2:10] == SEL_VESTING_VALIDATOR_DEPOSIT + + +def test_vesting_validator_exit_targets_vesting_contract(): + client = _make_client() + vesting_actions.vesting_validator_exit( + self=client, + vesting_contract_address=VESTING_ADDR, + wallet=WALLET_ADDR, + shares=42, + ) + tx = _last_tx(client) + assert tx["to"].lower() == VESTING_ADDR.lower() + assert tx["data"][2:10] == SEL_VESTING_VALIDATOR_EXIT + + +def test_vesting_validator_claim_targets_vesting_contract(): + client = _make_client() + vesting_actions.vesting_validator_claim( + self=client, + vesting_contract_address=VESTING_ADDR, + wallet=WALLET_ADDR, + ) + tx = _last_tx(client) + assert tx["to"].lower() == VESTING_ADDR.lower() + assert tx["data"][2:10] == SEL_VESTING_VALIDATOR_CLAIM + + +def test_vesting_validator_initiate_operator_transfer_targets_vesting_contract(): + client = _make_client() + vesting_actions.vesting_validator_initiate_operator_transfer( + self=client, + vesting_contract_address=VESTING_ADDR, + wallet=WALLET_ADDR, + new_operator=NEW_OPERATOR_ADDR, + ) + tx = _last_tx(client) + assert tx["to"].lower() == VESTING_ADDR.lower() + assert tx["data"][2:10] == SEL_VESTING_VALIDATOR_INITIATE_OPERATOR_TRANSFER + + +def test_vesting_validator_complete_operator_transfer_targets_vesting_contract(): + client = _make_client() + vesting_actions.vesting_validator_complete_operator_transfer( + self=client, + vesting_contract_address=VESTING_ADDR, + wallet=WALLET_ADDR, + ) + tx = _last_tx(client) + assert tx["to"].lower() == VESTING_ADDR.lower() + assert tx["data"][2:10] == SEL_VESTING_VALIDATOR_COMPLETE_OPERATOR_TRANSFER + + +def test_vesting_validator_cancel_operator_transfer_targets_vesting_contract(): + client = _make_client() + vesting_actions.vesting_validator_cancel_operator_transfer( + self=client, + vesting_contract_address=VESTING_ADDR, + wallet=WALLET_ADDR, + ) + tx = _last_tx(client) + assert tx["to"].lower() == VESTING_ADDR.lower() + assert tx["data"][2:10] == SEL_VESTING_VALIDATOR_CANCEL_OPERATOR_TRANSFER + + +def test_vesting_validator_set_identity_targets_vesting_contract(): + client = _make_client() + vesting_actions.vesting_validator_set_identity( + self=client, + vesting_contract_address=VESTING_ADDR, + wallet=WALLET_ADDR, + moniker="validator", + logo_uri="logo", + website="site", + description="desc", + email="email", + twitter="tw", + telegram="tg", + github="gh", + extra_cid="cid", + ) + tx = _last_tx(client) + _, args = _decode_vesting_tx(client, tx["data"]) + assert tx["to"].lower() == VESTING_ADDR.lower() + assert tx["data"][2:10] == SEL_VESTING_VALIDATOR_SET_IDENTITY + assert args["extraCid"] == b"cid" + + +def test_vesting_validator_set_identity_preserves_hex_extra_cid(): + client = _make_client() + vesting_actions.vesting_validator_set_identity( + self=client, + vesting_contract_address=VESTING_ADDR, + wallet=WALLET_ADDR, + moniker="validator", + logo_uri="logo", + website="site", + description="desc", + email="email", + twitter="tw", + telegram="tg", + github="gh", + extra_cid="0x1234", + ) + tx = _last_tx(client) + _, args = _decode_vesting_tx(client, tx["data"]) + assert args["extraCid"] == b"\x12\x34" + + +def test_write_requires_account(): + client = _make_client() + client.local_account = None + with pytest.raises(Exception, match="No account provided"): + vesting_actions.vesting_withdraw( + self=client, + vesting_contract_address=VESTING_ADDR, + amount=7, + ) + + +def test_vested_unvested_and_withdrawable_amount_reads(): + client = _make_client() + functions = SimpleNamespace( + vestedAmount=Mock(return_value=_call_result(11)), + unvestedAmount=Mock(return_value=_call_result(22)), + withdrawableAmount=Mock(return_value=_call_result(33)), + ) + client.w3.eth.contract = Mock(return_value=SimpleNamespace(functions=functions)) + + assert ( + vesting_actions.vested_amount( + self=client, vesting_contract_address=VESTING_ADDR + ) + == 11 + ) + assert ( + vesting_actions.unvested_amount( + self=client, vesting_contract_address=VESTING_ADDR + ) + == 22 + ) + assert ( + vesting_actions.withdrawable_amount( + self=client, vesting_contract_address=VESTING_ADDR + ) + == 33 + ) + + +def test_get_vesting_schedule_reads_schedule_fields(): + client = _make_client() + functions = SimpleNamespace( + name=Mock(return_value=_call_result("Founder")), + category=Mock(return_value=_call_result(1)), + beneficiary=Mock(return_value=_call_result(BENEFICIARY_ADDR)), + creator=Mock(return_value=_call_result(CREATOR_ADDR)), + revoker=Mock(return_value=_call_result(REVOKER_ADDR)), + factory=Mock(return_value=_call_result(FACTORY_ADDR)), + totalAmount=Mock(return_value=_call_result(1000)), + startDate=Mock(return_value=_call_result(100)), + cliffDuration=Mock(return_value=_call_result(200)), + periodDuration=Mock(return_value=_call_result(300)), + numberOfPeriods=Mock(return_value=_call_result(4)), + cliffUnlockBps=Mock(return_value=_call_result(500)), + needsManualUnlock=Mock(return_value=_call_result(False)), + ) + client.w3.eth.contract = Mock(return_value=SimpleNamespace(functions=functions)) + + schedule = vesting_actions.get_vesting_schedule( + self=client, vesting_contract_address=VESTING_ADDR + ) + + assert schedule == { + "name": "Founder", + "category": 1, + "beneficiary": BENEFICIARY_ADDR, + "creator": CREATOR_ADDR, + "revoker": REVOKER_ADDR, + "factory": FACTORY_ADDR, + "total_amount": 1000, + "start_date": 100, + "cliff_duration": 200, + "period_duration": 300, + "number_of_periods": 4, + "cliff_unlock_bps": 500, + "needs_manual_unlock": False, + } + + +def test_get_vesting_state_reads_state_fields(): + client = _make_client() + functions = SimpleNamespace( + manualUnlocked=Mock(return_value=_call_result(True)), + revoked=Mock(return_value=_call_result(False)), + vestingStopped=Mock(return_value=_call_result(False)), + totalWithdrawn=Mock(return_value=_call_result(1)), + vestedAtRevocation=Mock(return_value=_call_result(2)), + totalAmountAtRevocation=Mock(return_value=_call_result(3)), + revokedAt=Mock(return_value=_call_result(4)), + vestingStoppedAt=Mock(return_value=_call_result(5)), + vestedAtStop=Mock(return_value=_call_result(6)), + accumulatedRewards=Mock(return_value=_call_result(7)), + accumulatedLosses=Mock(return_value=_call_result(8)), + vestedAmount=Mock(return_value=_call_result(9)), + unvestedAmount=Mock(return_value=_call_result(10)), + withdrawableAmount=Mock(return_value=_call_result(11)), + ) + client.w3.eth.contract = Mock(return_value=SimpleNamespace(functions=functions)) + + state = vesting_actions.get_vesting_state( + self=client, vesting_contract_address=VESTING_ADDR + ) + + assert state == { + "manual_unlocked": True, + "revoked": False, + "vesting_stopped": False, + "total_withdrawn": 1, + "vested_at_revocation": 2, + "total_amount_at_revocation": 3, + "revoked_at": 4, + "vesting_stopped_at": 5, + "vested_at_stop": 6, + "accumulated_rewards": 7, + "accumulated_losses": 8, + "vested_amount": 9, + "unvested_amount": 10, + "withdrawable_amount": 11, + } + + +def test_get_vesting_stake_info_reads_validator_state(): + client = _make_client() + functions = SimpleNamespace( + depositedPerValidator=Mock(return_value=_call_result(123)), + pendingExitDeposited=Mock(return_value=_call_result(45)), + ) + client.w3.eth.contract = Mock(return_value=SimpleNamespace(functions=functions)) + + stake_info = vesting_actions.get_vesting_stake_info( + self=client, + vesting_contract_address=VESTING_ADDR, + validator=VALIDATOR_ADDR, + ) + + assert stake_info == {"deposited": 123, "pending_exit_deposited": 45} + checksum_validator = client.w3.to_checksum_address(VALIDATOR_ADDR) + functions.depositedPerValidator.assert_called_once_with(checksum_validator) + functions.pendingExitDeposited.assert_called_once_with(checksum_validator) + + +def test_get_validator_wallets_reads_wallet_list(): + client = _make_client() + functions = SimpleNamespace( + getValidatorWallets=Mock(return_value=_call_result([WALLET_ADDR])), + ) + client.w3.eth.contract = Mock(return_value=SimpleNamespace(functions=functions)) + + wallets = vesting_actions.get_validator_wallets( + self=client, vesting_contract_address=VESTING_ADDR + ) + + assert wallets == [WALLET_ADDR] + + +def test_validator_wallet_count_reads_wallet_count(): + client = _make_client() + functions = SimpleNamespace( + validatorWalletCount=Mock(return_value=_call_result(3)), + ) + client.w3.eth.contract = Mock(return_value=SimpleNamespace(functions=functions)) + + assert ( + vesting_actions.validator_wallet_count( + self=client, vesting_contract_address=VESTING_ADDR + ) + == 3 + ) + + +def test_validator_deposited_reads_wallet_deposit(): + client = _make_client() + functions = SimpleNamespace( + validatorDeposited=Mock(return_value=_call_result(123)), + ) + client.w3.eth.contract = Mock(return_value=SimpleNamespace(functions=functions)) + + deposited = vesting_actions.validator_deposited( + self=client, + vesting_contract_address=VESTING_ADDR, + wallet=WALLET_ADDR, + ) + + assert deposited == 123 + functions.validatorDeposited.assert_called_once_with( + client.w3.to_checksum_address(WALLET_ADDR) + ) + + +def test_is_validator_wallet_reads_membership(): + client = _make_client() + functions = SimpleNamespace( + isValidatorWallet=Mock(return_value=_call_result(True)), + ) + client.w3.eth.contract = Mock(return_value=SimpleNamespace(functions=functions)) + + is_wallet = vesting_actions.is_validator_wallet( + self=client, + vesting_contract_address=VESTING_ADDR, + wallet=WALLET_ADDR, + ) + + assert is_wallet is True + functions.isValidatorWallet.assert_called_once_with( + client.w3.to_checksum_address(WALLET_ADDR) + ) + + +def test_get_vesting_contract_reads_factory_mapping(): + client = _make_client() + functions = SimpleNamespace( + getVesting=Mock(return_value=_call_result(VESTING_ADDR)), + ) + client.w3.eth.contract = Mock(return_value=SimpleNamespace(functions=functions)) + + vesting_contract = vesting_actions.get_vesting_contract( + self=client, + vesting_factory_address=FACTORY_ADDR, + beneficiary=BENEFICIARY_ADDR, + ) + + assert vesting_contract == client.w3.to_checksum_address(VESTING_ADDR) + client.w3.eth.contract.assert_called_once_with( + address=client.w3.to_checksum_address(FACTORY_ADDR), abi=VESTING_ABI + ) + functions.getVesting.assert_called_once_with( + client.w3.to_checksum_address(BENEFICIARY_ADDR) + ) + + +def test_abi_includes_expected_functions_and_events(): + """Guard against the bundled ABI JSON drifting or truncating.""" + names = {e["name"] for e in VESTING_ABI if e.get("type") == "function"} + events = {e["name"] for e in VESTING_ABI if e.get("type") == "event"} + assert { + "vestingDelegatorJoin", + "vestingDelegatorExit", + "vestingDelegatorClaim", + "vestingValidatorJoin", + "vestingValidatorDeposit", + "vestingValidatorExit", + "vestingValidatorClaim", + "vestingValidatorInitiateOperatorTransfer", + "vestingValidatorCompleteOperatorTransfer", + "vestingValidatorCancelOperatorTransfer", + "vestingValidatorSetIdentity", + "vestingWithdraw", + "vestedAmount", + "unvestedAmount", + "withdrawableAmount", + "depositedPerValidator", + "pendingExitDeposited", + "getValidatorWallets", + "validatorWalletCount", + "validatorDeposited", + "isValidatorWallet", + "getVesting", + }.issubset(names) + assert { + "TokensWithdrawn", + "DelegatorJoined", + "DelegatorExited", + "DelegatorClaimed", + "ValidatorJoined", + "ValidatorDeposited", + "ValidatorExited", + "ValidatorClaimed", + "VestingCreated", + }.issubset(events) diff --git a/uv.lock b/uv.lock index f958102..fe9d491 100644 --- a/uv.lock +++ b/uv.lock @@ -434,7 +434,7 @@ wheels = [ [[package]] name = "genlayer-py" -version = "0.18.0" +version = "0.19.0rc2" source = { editable = "." } dependencies = [ { name = "web3" },